2012-04-16 16 views
6

Duplicar posible:
Why check this != null?¿Por qué String.Equals (Object obj) comprueba si esto == nulo?

// Determines whether two strings match. 
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 
public override bool Equals(Object obj) 
{ 
    //this is necessary to guard against reverse-pinvokes and 
    //other callers who do not use the callvirt instruction 
    if (this == null) 
     throw new NullReferenceException(); 

    String str = obj as String; 
    if (str == null) 
     return false; 

    if (Object.ReferenceEquals(this, obj)) 
     return true; 

    return EqualsHelper(this, str); 
} 

La parte que no entiendo es el hecho de que es la comprobación de la instancia actual, this, contra nula. El comentario es un poco confuso, así que me preguntaba ¿qué significa realmente ese comentario?

¿Alguien puede dar un ejemplo de cómo esto podría romperse si ese cheque no estaba allí, y esto significa que también debería colocar ese control en mis clases?

+0

@FlorianGreinacher: No es un posible duplicado, pero es casi un duplicado exacto, jajaja. Me pregunto por qué no apareció en "Relacionado" cuando escribía mi pregunta. –

Respuesta

6

Esa comprobación está allí como una protección contra el código nativo que puede invocar la función con un puntero nulo this. Esto no puede suceder en C#, por lo que no tiene que poner guardias similares en su código. Es muy posible que la clase String se haya escrito antes de que se completara C# y el autor podría haber pensado que es importante protegerse de los valores nulos, o tal vez es común llamar a String métodos desde código nativo y otros lugares que facilitan llamar a métodos en null .

Tenga en cuenta que incluso si logra que se le llame con un nulo this y no tiene la protección, todo lo que sucederá es que la excepción será ligeramente diferente. Puede ser una excepción diferente y puede ser lanzada por un miembro diferente, pero de lo contrario es poco probable que haga la diferencia.

En otras palabras, si la comprobación nula no estaba allí, el EqualsHelper (o una de sus calles) lanzaría la excepción en lugar de Equals. Como es deseable ocultar las funciones internas de la función visible para el usuario, tiene sentido poner la verificación al principio.

2
  • Los lenguajes como C# y VB.NET usan callvirt para lanzar NullReference antes de que se ingrese un método de instancia (esto == nulo) las verificaciones no son necesarias.
  • Los lenguajes como F # y Managed C++ (la mayoría de las veces) usan la instrucción de llamada, donde puede acceder a un método de instancia con un nulo este puntero. (esto == nulo) tiene un efecto.

La comprobación nula adicional no solo está pensada para estos últimos idiomas sino también para ayudar a la depuración a arrojar en la ubicación donde se produce el error (llamar a un método de instancia de un objeto nulo). Si no estuviera allí, puede llamar a cualquier método dentro de la clase sin ningún error, siempre que esto nunca sea una desreferencia (accede a las variables miembro). Esto puede ir tan lejos que en su objeto nulo varias llamadas a métodos funcionaron y de repente se devuelve una excepción de referencia nula (el método al que se accedió a los datos de la instancia).

Si observa las comprobaciones dentro de las clases de .NET, es evidente que solo en algunas clases destacadas, como la cadena, sí contienen dichas protecciones. Otros métodos como IndexOf no protegen contra esto. Esto es inconsistente, pero creo que la penalidad por el rendimiento para tales controles dobles nulos no valió la pena porque la mayoría de los usuarios del BCL son idiomas que usan la instrucción callvirt donde un segundo cheque nulo no ayuda.

+1

En F #, 'let x =" a ".Igual ("b") 'todavía compila a' callvirt' – colinfang

Cuestiones relacionadas