What is the point of "interrogation" in the type statement in C#?

Asked

Viewed 4,507 times

16

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 couldn’t understand why DateTime?.

What would be the difference between:

public DateTime? BirthDate { get; set}

And

public DateTime BirthDate { get; set }

What does this interrogation mean that comes after the guy?

3 answers

17


Specifically in this case (where the signal comes after some kind), it means that the primitive type can receive null as a 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 (I judge) important properties.

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

Take 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 same example on dotNetFiddle.

  • 1

    Did not know of the existence Nullable<type> thank you.

11

In this specific case it is a syntactic sugar to indicate a cancellable type. This means that your DateTime which would not normally accept a null value, may accept.

This is especially useful for use with database fields that usually accept null. But it can be used for anything.

Note that in type by value the default is something that represents a zero (whatever value is suitable to represent this), in general represented by the constant MinValue. When the guy is voidable, the default of it is the same of the types by reference, so it happens to be a null.

It is only interesting to have this feature in the language for types by value. Reference types accept nulls by default.

The voidable type is a simple structure with basically two members. One is the value and obviously 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 a type by value is invalid, it needs a given helper. Obviously there is a small overhead from memory.

The semantics remains 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 annulable equivalent (note that the types are different). The opposite is not true

If you are interested in understanding how it works, you have the class source Nullable.

In his example is without syntactic sugar would look like this:

public Nullable<DateTime> BirthDate { get; set; }

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

    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 properties HasValue and Value is not necessary and usually not recommended. These properties are available for the compiler and other tools to handle the type appropriately. Its use in "normal" code must be rare and must have a justification. The idea is that the type be used as if the null were native to it. Using them would make the use of the voidable type less transparent and decrease the resource’s syntactic sugar capacity.

Related: What is the meaning of the operator "??" and What is the operator "?."?

  • 1

    Well, then I’ll get used to these typing ideas... C# is a world far from PHP :)

  • 1

    You will understand the Nullable better after understanding the use of Generics.

6

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

public DateTime? BirthDate { get; set; }

is equivalent to the declaration

public Nullable<DateTime> BirthDate { get; set; }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.