What is the "question mark" in the C # type declaration? [duplicate]

13

I saw this code written in C # on the internet:

namespace Test
{
    [MicroEntitySetup(TableName = "Users")]
    public class User : MicroEntity<User>
    {
        [Key]
        public int id { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
        public bool isAdmin { get; set; }
        public DateTime? BirthDate { get; set; }
    }
}

As I'm learning C # now, I still do not understand why DateTime? .

What would be the difference between:

public DateTime? BirthDate { get; set}

E

public DateTime BirthDate { get; set }

What does this interrogation come after the type?

    
asked by anonymous 28.04.2016 / 20:26

3 answers

15

Specifically in this case (where the signal comes after some type), it means that the primitive type can receive null as value.

It's a syntax sugar for Nullable<Tipo>

Ex:

DateTime? data = null; // Vai funcionar
DateTime data = null;  // Erro -> DateTime não pode receber null

Detail:

The Nullable<Tipo> , has two properties (which I think) important.

The HasValue and Value . The HasValue is a boolean that determines if the variable has a value ( true ) or if it is null ( false ). The Value loads the value of the variable (if it is not null, obviously).

See the example:

int? nullable1 = null;
int? nullable2 = 10;

if(nullable1.HasValue) // HasValue = false
    WriteLine(nullable1);

if(nullable2.HasValue) // HasValue = true
{
    WriteLine(nullable2);       // Imprime 10
    WriteLine(nullable2.Value); // Imprime 10
}

See this example at dotNetFiddle.

    
28.04.2016 / 20:28
10

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.

    
28.04.2016 / 20:29
5

The query is a syntactic sugar to declare that a primitive type can have the null value (i.e., Nullable<T> ) - null is not a valid value for a primitive type. Using Nullable , you have a type that may have a primitive or null value. The statement

public DateTime? BirthDate { get; set; }

is equivalent to the declaration

public Nullable<DateTime> BirthDate { get; set; }
    
28.04.2016 / 20:28