To initial recommendation is always use the existing resource in the language until there is a reason not to use.
Functioning of the property
Understand that a property is just syntax sugar, i.e., in practice the compiler transforms a property into two methods. For example, creating a property of the type string
calling for Nome
, in fact internally will have a private field with a name similar to __Nome
and two methods with names close to string __getNome()
and void __setNome(string value)
.
The implementation of the first should be return __Nome;
and the second __Nome = value;
Optimizing
Some people should look at this and find that calling a method and do the set
or get
is slower than accessing the direct field. But this may not happen because probably the JIT compiler will optimize and end up making direct access to the field, eliminating the call to the method. And if you can’t do the optimization, there must be a good reason for that.
So, initially there is no reason to create methods getNome()
and setNome()
manually. No advantage. It may have the disadvantage of someone not understanding why you did it.
When not using
There are some situations that a method is preferable, but not necessarily the pure and simple exchange of property for a couple of methods get and set. The question is whether something should be a simple property or something more comprehensive.
A property:
- must be simple, should not perform complex operations;
- should not make exceptions explicitly or implicitly through calls to other methods internally, especially the get should provide a result always;
- may not take (probably few nanoseconds are recommended);
- avoids extra side effects (change status of other properties);
- is not a data conversion;
- is usually deterministic;
- does not return a copy of internal state unless it is a type by value;
- does not return a very large object, in general a array.
The programmer expects a property to be as trivial as taking or putting a value into a variable. If the property code does not meet the above guidelines is likely that it is not a property even. But nothing is so black in white.
Access to large or external data
If you will create a property called Clientes
that returns a list of clients obtained through a query to the database. This is not a property.
Something that is complex, makes access to external resources, can have several exceptions, is time consuming (milliseconds is an eternity) cannot be a property. In such cases, a method is more suitable because the programmer expects a method to be something more complex and that many things may occur in it.
So the solution is to create a field Clientes
and a method getClientes()
?
It may even be the solution. But understand that it is not a direct replacement of property, it is another operation. So it would be good to have another name and more suggestive than it does. For example ObtemTodosClientesNoDB()
or ObtemClientesSelecionadosNoDB()
. If you are going to save the result in a private field of the class or just return to who asked, it goes from the need.
If you’re thinking of any non-trivial logic of accessing and assigning the value, you’re probably not thinking of property.
Change of status
If a property should not change its value on its own. Often we see even the . NET missing in it. For example the property Now
class DateTime
does not have a stable value. Then the recommendation would be to use a method (probably DateTime.GetCurrentDateTime()
) and not a property.
There are controversies whether a database field should be represented by a property. The field can be changed by other external agents running your application at that time. It is not stable. On the other hand, a field has the face of property. You do not access fields in a DB with methods, you access with the field name or attribution to this name. However, some classes represent an image of a database data in memory and not the exact record. If you think this way, you are not violating the recommendation of stability of your content. Anyway, recommendations were created to be violated when there’s a good reason for this.
Properties should not have been changeable. So it should not be complex structures, especially data collections. But there are always exceptions.
Think about the fields (state) and the methods (behavior) a class should have. Then turn your fields into properties. This is a "rule" that helps define what is what. If by chance your property requires some simple logic in get
and/or in the set
, then you implement.
A property is better than a public field
At least it can give more flexibility for future maintenance. But this flexibility is not always required.
Contract and abstraction
A public field cannot be replaced without breaking the "contract" of the class. The access or assignment of value in a field cannot be "intercepted" to perform something different in the process of obtaining or assigning value, let alone putting such an intervention after the field has already been made publicly available for others to use. You can’t do that without breaking the contract.
So with the property, which is usually public, you encapsulate the private field (implementation detail), hide the concrete implementation and publish only the abstraction. Even if you have nothing to do with the property, having it right from the start in creating the class allows you to change its behavior in the future without breaking any contract.
This is why only Jitter does the optimization, it is done until the last moment, the optimization is done taking into account, including, the versioning of your application.
What is valid to do in a property
Normally the most a code property has is a validation before assignment, a simple calculation before returning a result, a write to log, a cache check, etc. When you have!
Some people think that using cache in property should be discouraged because the first execution can be slow. But there is another current that thinks that all the other accesses are very fast and so the property falls like a glove. The property only reads the value stored in the cache except on the first access that can perform a more complex processing. I like this last one, because it is already very common in several classes. Seems to me a good exception.
What not to do
A property should be seen as a substitute for a public field. Not as a substitute for methods. If these methods are not doing strictly operations directly linked to a specific private field, so they should not be thought of as properties.
There’s no problem having methods getIsso()
or setIsso()
whether they perform operations that go beyond simply accessing and assigning values to a field.
Simplifying
Note that the most common way to declare a property is
public string Nome { get; set; }
That is, it is practically the same as declaring a public field, but it has the advantage of abstraction, that is, it allows you to add some logic in the future get
and/or set
. It is rare to use logic within these elements.
With the property you facilitate both source and binary compatibility. In addition you gain capability of reflection that a field doesn’t have. And it’s easier thresh a property (fields may not have breakpoint) - improved feature in Visual Studio 2015.
Counterpoint
What many people don’t realize is that very simple systems that will be used for very few things, that its maintenance will be almost non-existent and done by one person, that’s not so important. In such systems it may be better to go in the simplest solution that is to leave the public field even. Unless you know in advance that you will need some processing in access or assignment. Even if one day you have to change an access, in a simple system, changing all the places of use is very easy, even more if you are using Visual Studio and more with Resharper.
Of course, if the system complicates a little bit, it will force you to touch it for more maintenance peace of mind. So make sure the system stays simple before you direct access.
Your specific problem
getDia
, getMes
, getAno
and isBissexto
would be their properties, right? Let’s change their names a little bit. Dia
, Mes
, Ano
and isBissexto
. Ready, now it becomes more suitable. Where you keep the day calls Dia
, where he keeps the month, calls Mes
and p/ save year, flame Ano
. Finally where you determine whether is leap, flame isBissexto
.
Code style
It is the standard adopted by most programmers that boolean values always have an "Is" (or "Eh" for those who like to participate, or É
for those who like accents) before the property name to make it clear that there is a binary value true or false. The property might well call just Bissexto
, but a IsBissexto
or EhBissexto
makes it clearer that what is stored there is whether "is or is not".
Example
So let’s assume you want some code out of class that can’t set these properties, they would be implemented like this:
public byte Dia { get; private set; }
public byte Mes { get; private set; }
public byte Ano { get; private set; }
public bool IsBissexto { get; private set; }
Remember that we do not convert a method to a property, we convert a field to a property.
Correct reasoning
Your reasoning about the IsBissexto
is correct. Even if there is a logic to get whether the year is leap or not, it is still a property. In fact it may be that the IsBissexto
or have what we call backing field, which is a private field that holds a value. It is as if the IsBissexto
is a virtual field. It can give you the result by calculating something. A simplified implementation (calculating leap is more complicated than that) would be:
public bool IsBissexto {
get {
return (Ano % 4 == 0);
}
}
In the proof class, really everything there seems to be property. Of course you could have, hypothetically, a method AceitarResposta()
that would not only put a value on repostaAluno
but also take the opportunity to update acertos
and perhaps one or two more things that were necessary when an answer is accepted in the object instance. If that AceitarResposta
operates in various properties, if it does more than just assign a value to a specific property, it is clearly a method, a class behavior.
Poor classes (anemic classes)
It is OK if a class has only properties. It is not so common, but there are cases like this.
Of course we don’t get into the question of class builder. In these cases it is common to have at least one builder for set the initial values of the properties when an object of this class is created. But there is another subject.
C#
In C# 6 this is easier and can even, in certain cases, dispense with the existence of a specific constructor. In C# 6 a property can have an initializer:
public Decimal Nota { get; set; } = 0.00M;
In C# 9 it is possible to let the property only be initialized:
public Decimal Nota { get; init; };
Property that does processing
The only caveat I make is whether there’s logic or not. A property may or may not have logic (conceptually it always has the implementation indicated in the second section of this text).
What the logic contained in it executes is that it determines whether it is a property of fact or should be a method. In the cases cited the existing possible logic is only something simple to give access to information, a calculation with class members. Eventually if the set
is available you could implement so:
private byte mes;
public byte Mes {
get {
return mes;
}
set {
if (value > 0 && value <= 12) {
mes = value;
}
}
}
Note that in cases where you implement a logic in set
or in the get
, cannot use the compact form of the property syntax. In this case you must declare a private field (normally the same name is used as the property, only starting with lowercase) and then declare the body of the method (because this set up there is a disguised method).
value
is a context "variable". Inside a set
there’s always that value
and it is always of the same property type. It is the parameter of the set
which receives the value you passed with attribution syntax.
Then use:
objeto.Mes = 3;
internally will be something like
objeto.__setMes(3);
Example of wrong use
One last example to reflect how a property can be wrong if it is trying to replace a method:
class BoxedInt {
public int Value { set; get; };
}
which is the same as:
class BoxedInt {
int value;
public int Value {
set { this.value = value; }
get { return this.value; }
}
}
Everything seems okay, but it’s not quite what it should be. We don’t really have a property there. In this case when you want to put a value in this class is when you are creating the class instance. Therefore the set
He’s actually the builder. And when you’re picking up the value, you’re doing more than picking up a value, you should make it explicit which operation is being done which is the unpacking of the value (Unboxing), then you ask to do the Unbox
. So the intention becomes more explicit:
class BoxedInt {
int value;
public BoxedInt(int v) { this.value = v; }
public int Unbox() { return this.value; }
}
Methods getter and Setter
In C# it is not common to use method only to do the get
and the set
values. Although properties are just methods getter and Setter, do not create methods even, as occurs in other languages.
Has a question about that and there I speak that not always the property is useful.
I put in the Github for future reference.
In this case, I think anemic means something good... if an anemic class does the same as another "chubby" class. I like the concept of doing more with less, being more expressive with less complexity... and so on.
– Miguel Angelo
One thing you can’t do with properties are asynchronous setters. The getter still gives, but I don’t think it’s cool, I prefer a method. An asynchronous Setter would be like this:
async Task SetValueT(T value)
– Miguel Angelo