2010-11-05 3 views
9

Sólo leer el artículo de MSDN sobre sustitución operadores de igualdad heremoldeada al objeto antes de la llegada nulo en primordial es igual a

El siguiente fragmento me confunde ...

// If parameter cannot be cast to Point return false. 
TwoDPoint p = obj as TwoDPoint; 
if ((System.Object)p == null) // <-- wtf? 
{ 
    return false; 
} 

¿Por qué hay un yeso para Object aquí para realizar la comparación null?

+1

¿Qué es TwoDPoint? Tal vez sea un tipo de valor :-D – Grzenio

+0

no. Compruebe el enlace ... – jgauffin

+0

Tienen una mejor guía para Visual Studio 2012. No han puesto el enlace en el artículo de 2005, así que lo puse aquí: [Cómo: Definir igualdad de valor para un tipo (Guía de programación C#) ] (http://msdn.microsoft.com/en-us/library/dd183755 (v = vs.110) .aspx). – Brk

Respuesta

9

Los operadores aplican a través de análisis estáticos (y sobrecargas), no métodos virtuales (sustituciones). Con el elenco, está haciendo un control de igualdad de referencia. Sin el modelo, puede ejecutar el operador TwoDPoint. Supongo que esto es para evitar problemas cuando se agrega un operador.

Personalmente, sin embargo, haría una verificación de referencia explícitamente con ReferenceEquals.

+0

+1 ... este estilo es obviamente terriblemente confuso (esta pregunta ha surgido varias veces). 'ReferenceEquals' existe, debe ser usado. –

+0

El artículo de MSDN continúa explicando por qué se debe usar ReferenceEquals :) –

+0

Obtendrás un Stackoverflow, como lo hice, cuando comparas tu objeto con nulo 'a == null', se volverá a ejecutar el reemplazado' == ' o '! =' una y otra vez, hasta que se cuelga. – ppumkin

0

Para forzar que se use el método Equals del objeto en lugar de su propia versión sobrecargada ... sólo una suposición ...

+0

Sí, pero * ¿por qué? – jgauffin

0

Esto no es inútil. Sin esa conversión, el operador == sobrecargado se llamaría recursivamente ...

+0

No. Acabo de probar el código sin el elenco. – jgauffin

+0

@jgauffin: Supuse que el código estaba sobrecargando el operador ==, en su lugar está sobrecargando Equals. En este caso, no veo ninguna razón para hacerlo, además de evitar errores si el operador == se introduce más adelante como sugiere @Marc Gravell. –

+0

El objetivo del artículo es que no puede anular Equals AND overload == sin usar un molde para Object. Si lo haces, obtienes una NullReferenceException cuando intentas hacer (myVariable == null). Pero estoy de acuerdo con el uso de ReferenceEquals. – tandrewnichols

0

el siguiente es la línea que hace el reparto

TwoDPoint p = obj as TwoDPoint 

la diferencia con el elenco "normal" es que el uso de "Como" no plantea una excepción si el objeto no es "moldeable". En este caso, si "p" no es TwoDPoint, el tipo no generará una excepción (el molde no es válido) sino que devolverá nulo.

if ((System.Object)p == null) // <-- wtf? 
{ 
    return false; 
} 

esta comprobación de código si el elenco fue muy bien, si no p debe ser nula por la razón anterior

+1

Preguntó por qué el molde '(System.Object)' está allí, nada más. – jgauffin

+0

tienes razón, simplemente malentendí la pregunta :-) –

3

No! si no lo hace, el tiempo de ejecución iniciará una llamada recursiva al operador de igualdad en el que se encuentra, lo que da como resultado una recursión infinita y, en consecuencia, un desbordamiento de la pila.

+1

No. No lo hará. Pruebe el código ... – jgauffin

+0

Sí, sin el molde recurrirá hasta 'StackOverflow' – ppumkin

0

Tenga en cuenta que esta es la documentación VS 2005. Supongo que las personas que escriben la documentación también tenían la misma pregunta y no podían encontrar una buena respuesta; el ejemplo fue cambiado para VS 2008. Aquí está el current version:

public bool Equals(TwoDPoint p) 
{ 
    // If parameter is null, return false. 
    if (Object.ReferenceEquals(p, null)) 
    { 
     return false; 
    } 

    // Optimization for a common success case. 
    if (Object.ReferenceEquals(this, p)) 
    { 
     return true; 
    } 

    // If run-time types are not exactly the same, return false. 
    if (this.GetType() != p.GetType()) 
     return false; 

    // Return true if the fields match. 
    // Note that the base class is not invoked because it is 
    // System.Object, which defines Equals as reference equality. 
    return (X == p.X) && (Y == p.Y); 
}