2011-01-31 15 views
9

¿Cuál es la forma más eficiente de verificar referencias nulas en objetos? He visto varias muestras de código que tienen diferentes maneras de verificar lo siguiente, ¿cuál es la más eficiente o la que se considera la mejor práctica para usar?¿Qué es una buena práctica para las verificaciones de referencia nulas?

Object.ReferenceEquals(item, null) 

item == null 

item != null 

Object.Equals(item, null) 

gracias

+4

Supongamos que uno de éstos eran 10 veces más lento que los demás, y lo utilizaron. ¿Lo notarías? Solo si estuviese en un punto de acceso costoso y raro. –

+1

@MikeDunlavey: Por supuesto, sería absolutamente estúpido elegir el que sea 10 veces más lento que cualquiera de las otras opciones presentadas (suponiendo que las otras opciones sean semánticamente correctas). La optimización no es prematura si la alternativa fuera descabellada y no conllevara ningún beneficio adicional. –

+2

@EdS .: Tal vez es estúpido y tonto, pero la gente lo hace todo el tiempo, y está realmente bien, si está en el código donde el rendimiento no es un problema. Cada vez que las personas 'nuevas' algo, están gastando cubos de ciclos, y si usan un lenguaje interpretado, están pagando una razón de velocidad de 1-2 órdenes de magnitud. –

Respuesta

8
  1. Object.ReferenceEquals(item, null) comparar las referencias y los iguales a item == null.
  2. Object.Equals(item, null) compare referencias para los tipos de referencia y bit a bit para los tipos de valores, pero en el reflector es igual a (item == null) || ((item != null && null != null) && item.Equals(null)).
  3. código item != null no siempre es igual a !(item == null), pero, por supuesto, el resultado debe ser el mismo.
  4. item == null código no es igual a null == item, es similar a typeof(item).Equals(object) y object.Equals(typeof(item)) llamadas de método.

se diferencia porque se puede anular !=, ==, Equals. Utilice métodos con implementación conocida, null == item es mejor codificar, pero más difícil de leer. Object.ReferenceEquals(null, item) puede ser más rápido o no.

P.S. use string.IsNullOrEmpty (item) too

+0

'null == item' es * no * más difícil de leer, y en muchos lenguajes de estilo c es una práctica mejor porque el hábito elimina la posibilidad de realizar una tarea cuando se pretende realizar una comparación. Por supuesto, el compilador de C# le ladra si intenta hacer una asignación en un condicional. Pero aún diría que es una buena práctica. No hice una evaluación comparativa, pero en el punto 4, aunque no es idéntico, las comparaciones son ciertamente equivalentes y se realizan las mismas operaciones, por lo que estaría bastante sorprendido si hay una diferencia en el rendimiento. – Craig

0

Primera 2 son los mismos de manera efectiva.

El último, sin embargo, no solo hace una verificación de referencia, y no debe utilizarse para la verificación nula.

2

siempre uso

item != null 

pero esto es difícil de leer que

item == null 

Object.ReferenceEquals se utiliza para comprobar si dos objetos son la misma instancia.

+1

¿Cómo se ve '! =' es más difícil de leer que '=='? –

+1

Dependiendo de la fuente que use, el signo de exclamación es menos visible que el signo de igual. por ejemplo, estos son menos píxeles en! than = si, por ejemplo, utilizaste en (! bool) es más fácil pasar por alto que (bool == false) depende de si tienes personal con problemas de visión o no, ¡supongo! – WraithNath

+1

Si eso * siempre * ha sido un problema para usted, parece que necesita cambiar las fuentes en su IDE. –

5

Para comparar a null, que haría uso de == o != siempre, porque para null siempre debe dar el mismo resultado que ReferenceEquals y Equals de todos modos (por lo que no hay necesidad de un código adicional).

Editar: Es cierto que == podría ser anulados para dar un resultado incorrecto para null (es decir, true), pero que los medios de anulación está libre de errores. Para que el código sea legible, me quedaría con == y !=.

+1

-1, no siempre. Puede ser diferente de .ReferenceEquals si esos operadores están sobrecargados (de una manera sin sentido, por supuesto) – nawfal

+0

nawfal, por supuesto, tiene razón; es posible solo en una anulación sin sentido (incorrecta) del operador '=='. Prefiero confiar en que '==' no es falso, y ser capaz de escribir un código mucho más legible (por ejemplo, 'null! = Obj' en oposición a' false == Object.ReferenceEquals (obj, null) ') – sinelaw

+0

pero nunca sabes. Y el código anterior se puede condensar a '! ReferenceEquals (obj, null)', o incluso mejor un método de extensión. Solo digo. – nawfal

3

ReferenceEquals es equivalente a (object)o1==(object)o2. Puede ser más rápido que o1==o2 si el operador de igualdad está sobrecargado. Object.Equals es probablemente un poco más lento.

La diferencia entre == y != no es el rendimiento, sino cómo debería ser su programa. Pueden ser un poco más lentos si el operador == y != están sobrecargados.

Pero no creo que la diferencia de rendimiento entre ellos importe en absoluto. Elegiría el que sea más fácil de leer. Y eso generalmente es == o !=.

Si lanzo una excepción que suelen utilizar == como en:

if(o == null) 
    throw new ...; 

If null resultados en un no-op entonces por lo general != es apropiado

if(x != null) 
{ 
    ... 
} 
+0

Hmm. 'ReferenceEquals' es equivalente a' (object) o1 == (object) o2' depende del conocimiento explícito de que el operador de comparación del tipo de datos System.Object hace una comparación de referencia. Claro, tal vez un buen programador debería saber eso. Pero se siente algo "inteligente" y, por lo tanto, un poco oscuro si estás escaneando el código en busca de comprensión. No me refiero a la falta de respeto al decir eso, pero preferiría la claridad sobre la inteligente siempre que sea razonable. – Craig

3

Como extra, ¡no olvide contratos de código en .NET 4.0!

System.Diagnostics.Contracts.Contract.Requires(item != null); 

Lo que no solo es bueno y claro, sino que permite la verificación del tiempo de compilación. Ver Code Contracts en msdn.

2

1)

Object.ReferenceEquals(item, null) 

Esta es una buena manera. No es tan conciso como me gustaría, pero sigue siendo genial y te dice exactamente cuál es la intención.

2)

item == null 

item != null 

No hay nada malo con esto (que es el más elegante) si está seguro de == y posteriormente != está sobrecargado correctamente. Es fácil de escribir (sobrecargar) malos operadores de igualdad (y a menudo hecho). Pero el problema real es cuando intenta sobrecargar el operador == en una clase (digamos de valor semántico). No puede usar == para verificaciones nulas dentro de la función de sobrecarga == de la clase since that will cause an infinite recursion. Para tener un estilo consistente, confío en otra cosa.

3)

Object.Equals(item, null) 

Una vez más internamente hace un ReferenceEquals por lo que no tiene mucho sentido, pero si es semánticamente tiene más sentido para usted, y luego ir con esto.

4)

Mi enfoque es hacer

(object)item == null 

sobre la que me apoyo en el propio operador de igualdad object 's que no puede ir mal. No así legible por lo que sólo debe ser envuelta en un método de extensión personalizada y una sobrecarga:

public static bool IsNull<T>(this T obj) where T : class 
{ 
    return (object)obj == null; 
} 

public static bool IsNull<T>(this T? obj) where T : struct 
{ 
    return !obj.HasValue; 
} 

Tiene más sentido ya que tendrá que comprobar en contra DBNull es demasiado a menudo. ¡Así que ahora tengo un estilo consistente en todas partes!

public static bool IsNull<T>(this T obj) where T : class 
{ 
    return (object)obj == null || obj == DBNull.Value; 
} 

(No se quite el casting (object) ya que eso es lo que va a prevenir la repetición infinita cuando la sobrecarga == como se dijo antes)

Además la restricción impide IsNull sobre los tipos de valor. Ahora es tan dulce como llamar

object obj = new object(); 
Guid? guid = null; 
bool b = obj.IsNull(); // false 
b = guid.IsNull(); // true 
2.IsNull(); // error 

También he encontrado (object)item == null está very very very slightly faster than Object.ReferenceEquals(item, null) o object.Equals(,) para el caso, pero sólo si es importante (actualmente estoy trabajando en algo en lo que he de micro-optimizar todo!) .

Para ver una guía completa sobre la utilización de controles de igualdad, ver What is "Best Practice" For Comparing Two Instances of a Reference Type?

Cuestiones relacionadas