¿Qué significa el signo de interrogación y el operador de puntos? significa en C # 6.0?

359

Con C # 6.0 en la vista previa de VS2015 tenemos un nuevo operador, ?. , que se puede usar así:

public class A {
   string PropertyOfA { get; set; }
}

...

var a = new A();
var foo = "bar";
if(a?.PropertyOfA != foo) {
   //somecode
}

¿Qué hace exactamente?

Landeeyo
fuente

Respuestas:

500

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
Jon Skeet
fuente
8
¿No se llama operador condicional nulo ?
Fugas
1
@SLaks: pensé que era "nulo condicional" pero podría estar equivocado. La última vez que revisé los documentos de características del idioma Roslyn, tampoco había cambiado el nombre. Tal vez la fuente es la autoridad aquí, lo comprobará.
Jon Skeet
3
@SLaks: Claro. En SyntaxKind aparentemente es ConditionalAccessExpression, lo cual es molesto para ninguno de ellos ...
Jon Skeet
12
prefiero el nombre de operador "Elvis": P
Ahmed ilyas
3
Solo para el registro, he visto cinco nombres diferentes para este operador: navegación segura, condicional nulo, propagación nula, acceso condicional, Elvis.
Gigi
81

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);

Ejemplo de DotNetFiddle :

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

Erik Philips
fuente
27
Para salvar a las personas que buscan qué? es .. Es el operador de fusión nula y devolverá Nombre si no es nulo, de lo contrario devolverá "N / A".
Steve
66
@Erik Philips Creo que es necesario agregar || 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
RazvanR
2
@ ErikPhilips No en la misma página, supongo. Intente ver qué sucede en ambos casos, si Model.Model2.Model3.Model4.Namees así null.
RazvanR
1
El resultado es "N / A", nuevamente LEA EL PRIMER COMENTARIO. DotNetFiddle.Net Ejemplo de trabajo .
Erik Philips
77
@ErikPhilips: Eso no tiene nada que ver con el primer comentario, ya que esto no se relaciona con su primer ejemplo. En esto, saltarías a la 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
derM
3

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í:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators

Zeeshan Adil
fuente