c# - puntos - signos de puntuacion
¿Por qué C#requiere paréntesis cuando se usan elementos nulables en una expresión? (2)
¿Alguien podría explicarme por qué se necesitan los paréntesis?
Porque Identity()
devuelve un Foo
(¿no es un Foo?
) Y, por lo tanto, no tiene ninguna propiedad Value
. Si foo
es nulo, el nulo se propagará a través de la llamada de Identity
.
Cuando coloca paréntesis alrededor, los resultados de la expresión son Nullable<Foo>
que tiene una propiedad Value
.
También tenga en cuenta que si foo
es nulo, estará llamando a Value
en un Nullable<Foo>
que no tiene ningún valor, y obtendrá una excepción en tiempo de ejecución . Algunos analizadores estáticos reconocerán que tiene una posible excepción de referencia nula esperando a suceder y le avisará.
Si los expandes a sus equivalentes sin propagación nula, será más claro:
Foo foo1;
if(foo != null)
{
foo1 = foo.Identity().Value; // not possible - Foo has no Value property.
}
else
{
foo1 = null; // also not possible
}
Foo foo2;
Foo? temp;
if(foo != null)
{
temp = foo.Identity();
}
else
{
temp = null; // actually a Nullable<Foo> with no value
}
foo2 = temp.Value; // legal, but will throw an exception at run-time if foo is null
Si
Identity()
devuelveFoo
, ¿por quéFoo foo3 = foo?.Identity();
no compilar?
El equivalente de eso sería:
Foo foo3
if(foo != null)
{
foo3 = foo.Identity();
}
else
{
foo3 = null; // not possible
}
Soy nuevo en C # y mientras exploraba las características del lenguaje, encontré algo extraño:
struct Foo
{
public Foo Identity() { return this; }
public static void Bar(Foo? foo)
{
Foo foo1 = foo?.Identity().Value; // Does not compile
Foo foo2 = (foo?.Identity()).Value; // Compiles
}
}
¿Alguien podría explicarme por qué se necesitan los paréntesis?
Creo que fue una buena decisión del equipo c # para hacerlo de esta manera. Considere el siguiente escenario:
Si la estructura fue:
struct Foo
{
public int ID { set; get; }
public Foo Identity() { return this; }
public static void Bar(Foo? foo)
{
int? foo1 = foo?.Identity().ID; // compile
Foo foo2 = (foo?.Identity()).Value; // Compiles
}
}
Si no necesita el paréntesis para acceder al resultado Nullable, no podrá acceder a la propiedad ID
. Dado que a continuación no se compilará:
int? foo2 = (foo?.Identity()).GetValueOrDefault()?.ID
Cuando escribes foo?.Identity().
que es después de .
es del tipo Foo
devuelto por Identity()
. Sin embargo, en (foo?.Identity()).
que es después de .
es Foo?
que es el resultado real de toda la declaración foo?.Identity().