Respuestas:
Es el condicional nulo operador . Básicamente significa:
"Evalúe el primer operando; si es nulo, deténgase, con un resultado de nulo. De lo contrario, evalúe el segundo operando (como acceso de miembro del primer operando)".
En su ejemplo, el punto es que si a
es así null
, entonces a?.PropertyOfA
evaluará en null
lugar de lanzar una excepción; luego comparará esa null
referencia con foo
(usando la ==
sobrecarga de la cadena ), encontrará que no son iguales y la ejecución irá al cuerpo delif
declaración .
En otras palabras, es así:
string bar = (a == null ? null : a.PropertyOfA);
if (bar != foo)
{
...
}
... excepto que a
solo se evalúa una vez.
Tenga en cuenta que esto también puede cambiar el tipo de expresión. Por ejemplo, considere FileInfo.Length
. Esa es una propiedad de tipo long
, pero si la usa con el operador condicional nulo, termina con una expresión de tipo long?
:
FileInfo fi = ...; // fi could be null
long? length = fi?.Length; // If fi is null, length will be null
Puede ser muy útil al acoplar una jerarquía y / o asignar objetos. En vez de:
if (Model.Model2 == null
|| Model.Model2.Model3 == null
|| Model.Model2.Model3.Model4 == null
|| Model.Model2.Model3.Model4.Name == null)
{
mapped.Name = "N/A"
}
else
{
mapped.Name = Model.Model2.Model3.Model4.Name;
}
Se puede escribir como (la misma lógica que la anterior)
mapped.Name = Model.Model2?.Model3?.Model4?.Name ?? "N/A";
DotNetFiddle.Net Ejemplo de trabajo .
(el operador ?? o nulo-coalescente es diferente del operador condicional? o nulo ).
También se puede usar fuera de los operadores de asignación con Action. En vez de
Action<TValue> myAction = null;
if (myAction != null)
{
myAction(TValue);
}
Se puede simplificar para:
myAction?.Invoke(TValue);
utilizando el sistema;
public class Program
{
public static void Main()
{
Action<string> consoleWrite = null;
consoleWrite?.Invoke("Test 1");
consoleWrite = (s) => Console.WriteLine(s);
consoleWrite?.Invoke("Test 2");
}
}
Resultado:
Prueba 2
|| Model.Model2.Model3.Model4.Name == null
a tener la misma lógica, si no en caso Model.Model2.Model3.Model4.Name
es null
, mapped.Name
permaneceránull
Model.Model2.Model3.Model4.Name
es así null
.
else
rama y tendrías mapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null
, mientras que tu segundo ejemplo lo sustituiría mapped.Name = "N/A"
. Vea el DotNetFiddle editado
Esto es relativamente nuevo en C #, lo que nos facilita llamar las funciones con respecto a nulo o no nulo valores en el encadenamiento de métodos.
La vieja forma de lograr lo mismo era:
var functionCaller = this.member;
if (functionCaller!= null)
functionCaller.someFunction(var someParam);
y ahora se ha hecho mucho más fácil con solo:
member?.someFunction(var someParam);
Le recomiendo que lo lea aquí: