I understand the many benefits of providing an interface to access the members of a class indirectly. My question is: isn\'t that already something you can accomplish in jus
One of the popular ways of looking at object-oriented programming is to model the classes in our programs on the concepts in our heads.
The concepts in our heads are based on the actual objects that we perceive around us (whether we perceive them or we communicate with others who have perceived them).
The objects around us - furniture, animals, space shuttles, etc. - have specific properties and act in specific ways.
That's where we get properties and methods.
In C#, a property may not be reducible to a single field-get or field-set (for example, it may require additional checks or there may be caching involved or any number of reasons). So we need a separate concept of properties with get-methods and set-methods to make our programs closer to the concepts we want them to model.
Properties at the essence are get/set method pairs.
Properties are a runtime supported method of exposing a pair of get set methods that have metadata support which means they are discoverable using reflection without guessing what methods are supposed to form the accessor based on method name and signature.
The other advantage of properties is that they act like fields syntactically, and not like methods, which has the advantage of creating more clean code.
I'm inclined to think a get/set function is more readable than a property since it is unambiguously a function as opposed to a straight-up value.
Most of the time properties are inlined by the Jit engine, because they are very simple, which means most of the time properties act like fields more than they act like functions, so they are closer to how fields behave than functions.
In the case of properties it doesn't mater if there is ambiguity between a function call and field access because for the greatest part you don't pay the function call cost, property getters and setters, because of their simplicity, are high candidates for inlining, which means that cost wise the are closer to fields than function calls *.
Having properties not only in the language but in the clr means that everyone on .NET can rely on their meta-data. A property has a connotation of get being without side effects and both get and set being a fast operation. Many tools use these assumption: the winforms designer, LINQ to SQL...
So it is not only about convenience but also about having an additional piece of metadata.
Here are other typical assumptions:
customer.Name = "a";
Assert.IsTrue(customer.Name == "a");
try { var ignored = customer.Name; }
catch { Assert.Fail("Exceptions are not expected"); }
Two big advantages to properties:
for me, it's easy:
myprop = myvalue;
console.writeline(myprop);
no need for
mysetfunc(myvalue);
console.writeline(mygetprop);
easier to remember 1 thing than 2
With get
and set
methods you have to decide to use them from the start and almost always write a lot of boilerplate code for every public property your classes expose.
class Point
{
private int x, y;
// Ew, pointless boilerplate!
public int getX() { return x; }
public void setX(int x) { this.x = x; }
public int getY() { return y; }
public void setY(int y) { this.y = y; }
}
// ...
Point p = new Point();
p.setX(5);
p.setY(10);
With properties you can eliminate the boilerplate getters and setters for the 90% of properties that have only trivial getters and setters. You can just have public variables exposed directly
class Point
{
public int x, y;
}
Point p = new Point();
p.x = 5;
p.y = 10;
Then later if you decide you want to add some behavior to your public variables you can switch them to properties with actual behavior in the get
or set
methods. The up side here is that users of your class are not affected at all. Nothing's changed; they don't have to switch from point.x = 5
to point.setX(5)
. Your public interface is stable, allowing you to use plain variables at first and switch to slower get
/set
methods later when you add some guarding/logging/whatever.
class Point
{
public int x { get; set; }
}
// No change!
Point p = new Point();
p.x = 5;
p.y = 10;
(Now strictly speaking, your syntactical interface hasn't changed, but your class's compiled interface has changed, so you do have to recompile all the code that uses your class if you switch from variables to properties. You can't get away with just recompiling your class and dropping that in place of the old class, if your class is part of a widely-used library, say. Your library's users would have to recompile their code against the new version of your library.)