O
This is the operator conditional access or null propagation or navigation. I haven't chosen which one to use But I think the second is better.As it was so frequent to check if an object is null before doing any operation (as shown in the first example), it was a https://pt.stackoverflow.com/a/16204/101 .Note that access to any member of the object can be "protected" with this operator. Methods can also be called. Obviously the call will only occur if the object is not null.The result of an expression objeto ?. membro it will be null, in case objeto be it null. And as the expressions can be chained, the first null that he find all the other sub-expressions found below will null too. He won't even try to evaluate the rest, the final result will be null. And this is important, she's a short-circuit operation, that is, she doesn't even try to perform the rest when there's no more to do.The two codes presented in the question No are exactly equivalent. In this case it will be, by coincidence, because it is a specific case rarely used where it is wanted as a result default a null. In this case the initialization of string location is a null in any situation. But think that if it had been initialized with "", that is, if it were one string empty, it would be different.In the first at the end of the operation vendor is null, content location will not be changed, that is, it will be worth "". In the second code it will be worth null, after all the result of an operation with an object null It is null.Let's see more about the operatorThis code will cause an exception in the last line by trying to access a null object:string texto = null;
string parte = "";
parte = texto?.Substring(0, 1);
WriteLine($"{parte.Length}");
Obviously we could have used the operator ?. before Length and avoid the exception.If you add this line:int tamanho = parte.Length;
It generates an exception because it cannot take the size of a null object. Right? So let's do this:int tamanho = parte?.Length;
Do you?No compilation. After all now the expression possibly results a null. One int can't be null. Then we'd have to do this:int? tamanho = parte?.Length;
An annullable integer may contain all possible results of this expression, including the value null.It's just that in this case you're using a different guy than you usually use just to solve a problem that didn't exist. Here it is better to do the old way:int tamanho = parte != null ? parte.Length : 0;
or merging the old with the new:int tamanho = parte?.Length ?? 0;
Note that the same operator may have different syntax in another context:Cliente cliente = clientes?[0]; //isto também é o operador de propagação de nulo
Another example of simplification is in checking whether an object has a member:(objeto as IExemplo)?.Exemplo();
If objeto do not implement this interface IExemplo, the result of the operation will be zero, so the method Exemplo() will not be called and will not cause error.In thesis would help programmers be more careful with code. There's a lot of code out there that doesn't make a mistake. null reference by coincidence. One day, it falls into the situation that the object is null and the application breaks without the incauto being noticed. Although I don't know if it's going to help a lot because it has a lot of programmer who doesn't know the "news" of C#3, and some even C#2. And obviously you don't even know everything in C# 1. It will also happen of the person to think that this solves everything, that must use everywhere, without thinking. The member access operator . or [] should still be the standard access operator.Thread-safeYour use can be more thread-safe in some cases by using a temporary variable to store the expression result. Example of gain://necessário para ser thread-safe
EventHandler<decimal> precoOnChanged = OnPrecoChanged;
if (precoOnChanged != null) {
preco = value;
precoOnChanged (this, value);
}
It turns into:preco = value;
OnPrecoChanged?.Invoke(this, value) //Invoke é usado p/ resolver ambiguidade c/ delegate
Prevent the null from happeningA .NET 4 feature that people ignore is the use of contracts (it has been abandoned lately). With it it is possible neither to need this and to avoid zero checks in runtime, detecting in development time:public int ProcuraTeste(string texto) { //não compila se texto for null
Contract.Requires(texto != null); //isto pode ser eliminado do runtime
return texto.IndexOf("teste");
}
https://github.com/maniero/SOpt/blob/master/CSharp/Operator/NullPropagation.cs .Of course this is not a solution to everything. There are cases you can only know in runtime, that is, the null is something expected as a valid value. https://pt.stackoverflow.com/q/90363/101 . If it was invalid, the type system, the compiler or static analysis should detect and prevent it.Simplifying without this operatorAs additional information, in C# 5 you can simplify the code a bit:if (vendor != null && vendor.ContactPerson != null && vendor.ContactPerson.HomeAddress != null)
location = vendor.ContactPerson.HomeAddress.LineOne;