operator check c# generics null value-type null-check

c# - check - ¿Comparando un genérico contra un nulo que podría ser un valor o un tipo de referencia?



check if object is null c# (2)

A propósito, solo estoy comprobando contra null porque no quiero restringir un ValueType de ser igual a su default(T)

Esa es una buena idea, pero no te preocupes, ya estás cubierto allí. No es legal comparar una T contra el default(T) usando == en primer lugar; la resolución de sobrecarga no encontrará un mejor operador == único.

Por supuesto, podrías hacer la comparación con .Equals pero luego corres el riesgo de chocar si el receptor es nulo, que es precisamente lo que intentas evitar.

¿Hay una forma más estándar de manejar esta situación?

No. Comparando con nulo es lo correcto para hacer aquí.

Como dice la especificación C # en la sección 7.10.6: " La construcción x == null está permitida aunque T podría representar un tipo de valor, y el resultado simplemente se define como falso cuando T es un tipo de valor " .

¿Hay alguna posibilidad de que surja un problema de esto?

Por supuesto. El hecho de que el código compila no significa que tenga la semántica que pretende. Escribe algunas pruebas

¿Qué sucede realmente bajo el capó cuando hago una llamada y paso un tipo de valor?

La pregunta es ambigua Permítanme reformularlo en dos preguntas:

¿Qué sucede realmente bajo el capó cuando hago una llamada al método genérico con un argumento tipo que es un tipo de valor que no admite nulos?

El jitter compila el método en la primera invocación con esa construcción. Cuando la fluctuación de fase detecta la verificación nula, la reemplaza por "falsa" porque sabe que ningún tipo de valor que no admite nulos será igual a nulo.

¿Qué sucede realmente bajo el capó cuando hago una llamada al método genérico con un argumento tipo que es un tipo de referencia pero un argumento que es un tipo de estructura? Por ejemplo:

interface IFoo : ISomeInterface<IFoo> {} struct SFoo : IFoo { whatever } ... DoFooInternal<IFoo>(new SFoo());

En ese caso, la fluctuación de fase no puede elide la verificación nula y el sitio de llamada no puede evitar el boxeo. La instancia de SFoo aparecerá en un recuadro y se verificará la referencia al SFoo enmarcado para ver si es nulo.

public void DoFoo<T>(T foo) where T : ISomeInterface<T> { //possible compare of value type with ''null''. if (foo == null) throw new ArgumentNullException("foo"); }

A propósito, solo estoy comprobando contra nulo porque no quiero restringir un ValueType de ser igual a su default(T) . Mi código se compila y funciona de esta manera (ReSharper se queja, pero no CodeAnalysis). Aunque me pregunto:

  • ¿Hay una forma más estándar de manejar esta situación?
  • ¿Hay alguna posibilidad de que surja un problema de esto?
  • ¿Qué sucede realmente bajo el capó cuando hago una llamada y paso un tipo de valor?

No, no habrá ningún problema, pero si desea que desaparezca la advertencia, puede usar lo siguiente:

public void DoFoo<T>(T foo) where T : ISomeInterface<T> { if (ReferenceEquals(foo, null)) throw new ArgumentNullException("foo"); }

Alternativamente, puedes hacer algo como esto:

// when calling this with an actual T parameter, you have to either specify the type // explicitly or cast the parameter to T?. public void DoFoo<T>(T? foo) where T : struct, ISomeInterface<T> { if (foo == null) { // throw... } DoFooInternal(foo.Value); } public void DoFoo<T>(T foo) where T : class, ISomeInterface<T> { if (foo == null) { // throw... } DoFooInternal(foo); } private void DoFooInternal<T>(T foo) where T : ISomeInterface<T> { // actual implementation }