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 aes así null, entonces a?.PropertyOfAevaluará en nulllugar de lanzar una excepción; luego comparará esa nullreferencia 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 asolo 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.Namees null, mapped.Namepermaneceránull
Model.Model2.Model3.Model4.Namees así null.
elserama 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í: