In this specific case it is a syntactic sugar to indicate a nullable type . This means that your% of% would not normally accept a null value, you can accept.
This is especially useful for use with database fields that usually accept nulls. But it can be used for anything.
Note that in type by value, usually default is something that represents a zero (whatever value is appropriate to represent it), usually represented by the DateTime
constant. When the type pass is nullable, the default is the same as the type by reference, so it becomes a MinValue
.
It's only interesting to have this feature in the language for types by value. Types by reference accept nulls by default .
The nullable type is a simple structure with basically two members. One is the value and obviously it is of the main type and the other is a Boolean indicator whether it is null or not. Obviously if it is null, the value will not be available. This is necessary because no value of one type per value is invalid, you need an auxiliary one. Obviously there is a small overhead of memory.
The semantics remain the type by value, but some small discrepancies can be observed in some very specific situations.
Every type by value can be implicitly converted to its nullable counterpart (note that the types are different). The opposite is not true
If you are interested in understanding how it works, you have source of class null
. .
In your example without the syntactic sugar would look like this:
public Nullable<DateTime> BirthDate { get; set; }
See dotNetFiddle .
DateTime dt = DateTime.Now;
DateTime? dtn = null;
WriteLine(dt);
WriteLine(dtn);
dtn = dt;
WriteLine(dtn);
dt = dtn ?? default(DateTime); //daria erro de compilação se não fizesse esta verificação
WriteLine(dtn);
dt = dtn.GetValueOrDefault(); //também pode usar isto que faz a verificação internamente
WriteLine(dtn);
if (dtn != null) {
WriteLine("tem valor");
}
if (dtn.HasValue) { //dá o mesmo resultado e seu uso é dispensável
WriteLine("tem valor");
}
Note that direct use of the Nullable
and HasValue
properties is not necessary and is not usually recommended. These properties are available to the compiler and other tools to handle the type properly. Its use in "normal" code should be rare and should have a justification. The idea is that the type be used as if the null were native to it. Using them would make use of the nullable type less transparent and would decrease the resource's syntactic capacity.
Related: What is the meaning of the "??" operator and operator.