2010-05-25 10 views
5

Por qué hacer esto:((System.Object) p == null)

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

lugar de esto:

// If parameter cannot be cast to Point return false. 
    TwoDPoint p = obj as TwoDPoint; 
    if (p == null) 
    { 
     return false; 
    } 

No entiendo por qué te gustaría escribir alguna vez ((Sistema .Objeto) p)?

Saludos,

Dan

+1

No necesita hacerlo. – ChrisF

+1

Estoy esperando que él diga que así es como su maestro dijo que lo hiciera o algo :) – Earlz

+3

Bien, pero ... http://msdn.microsoft.com/en-us/library/ms173147(VS.80) .aspx –

Respuesta

12

os echan a object cuando no sabe o no puede estar seguro de si la clase original ha anulado operator ==:

using System; 
class AlwaysEqual 
{ 
    public static bool operator ==(AlwaysEqual a, AlwaysEqual b) 
    { 
     return true; 
    } 

    public static bool operator !=(AlwaysEqual a, AlwaysEqual b) 
    { 
     return true; 
    } 
} 


class Program 
{ 
    static void Main() 
    { 
     object o = new AlwaysEqual(); 
     AlwaysEqual ae = o as AlwaysEqual; 

     if (ae == null) 
     { 
      Console.WriteLine("ae is null"); 
     } 

     if ((object)ae == null) 
     { 
      Console.WriteLine("(object)ae is null"); 
     } 
    } 
} 

Este código de salidas solo"ae is null", que obviamente no es el caso. El elenco a object evita el class operator == y es por lo tanto un verdadero control de referencia contra null.

+0

Entonces, ¿fundir a (System.Object) forzaría la invocación de "==" en Object? Extraño ... – OscarRyz

+5

Siempre prefiero la sintaxis 'object.ReferenceEquals (obj, null)' en estas situaciones. Explica la intención del código mucho más claramente. – LukeH

+0

Me están arrastrando lejos; pero me gustaría preguntar/investigar la pregunta (intentar y reformular en breve) "cuando un experto corrige el texto msdn si elaboran más?". Ahora, eso está cargado, pero tengo que irme ... –

1

habla claro, no tiene sentido. Siempre se puede asignar nulo (excepto para elementos no nulables como ints y structs) independientemente del tipo, por lo que siempre se puede verificar. El elenco no es necesario

Si TwoDPoint es un tipo que no admite nulos, como por ejemplo una estructura, entonces puede tener un punto. El caché (System.Object) encapsularía efectivamente la estructura en un objeto anulable. Pero si ese fuera el caso, entonces obj as TwoDPoint no sería válido. Necesitaría obj as TwoDPoint? para que sea nulo. (no se puede usar como con elementos no nulables)

+0

Hmm está bien. Tal vez ese es el punto, el no-nulables que es. Voy a verlo un poco más, gracias. Si tiene el tiempo - http://msdn.microsoft.com/en-us/library/ms173147(VS.80).aspx Saludos, Dan –

+0

@Daniel vea mi edición de por qué no es un no- problema de nullable. En cuanto a su enlace sin embargo. Es bastante curioso la sobrecarga del operador '=='. pero la función 'Equals' no es estática, de modo que si no apunta a un objeto válido, ¿qué ocurre? Esa es la pregunta correcta :) – Earlz

+0

@ Daniel Creo que @Mark tiene razón en este caso. – Earlz

1

Todos los objetos en .NET se derivan de System.Object, por lo que no es necesario realizar una conversión explícita.

+0

Cool - sí, me tomó un tiempo; tienes razón, ya veo. Gracias. El msdn http://msdn.microsoft.com/en-us/library/ms173147(VS.80).aspx me confundió. Lo siento. –

1

Y aún más concisa sería:

if (!(obj is TwoDPoint)) { 
    return false; 
} 
+1

También sería más eficiente si solo está comprobando que 'p' es del tipo correcto. – ChrisF

1

Tiene sentido si ese código está dentro de Object.Equals y no desea invocar al operador de igualdad (que podría, por ejemplo, llamar erróneamente al Equals). Casting to object permite llamar al operador de igualdad estándar, que compara las referencias.

Normalmente, se usaría Object.ReferenceEquals comparar una instancia de un objeto a null dentro Equals anulación.

Por ejemplo, esto podría causar un desbordamiento de pila:

public class Point { 
    public override bool Equals (object other) { 
    var otherPoint = other as Point; 

    if (other == null) 
     return false; 

    //... 
    } 

    public static bool operator == (Point l, Point r) { 
    //... 
    //null checks 
    if (!l.Equals(r)) 
     return false; 
    } 
} 

En el operador de igualdad ejemplo anterior llama Equals y debido otherPoint variable es de tipo Point, sería invocar el operador de igualdad, haciendo que la recursividad infinita.

Normalmente, cuando se reemplaza Equals y se define el operador de igualdad, que pondría a la lógica de comparación en el operador e invocar que a partir de la anulación Equals. Tenga en cuenta que se recomienda que la clase sea inmutable si ambas se anulan.

public class Point { 
    public override bool Equals (object other) { 
    var otherPoint = other as Point; 
    return this == otherPoint; 
    } 

    //must override GetHashCode() as well 

    public static bool operator == (Point l, Point r) { 
    if (Object.ReferenceEquals(l, null) && Object.ReferenceEquals(r, null)) 
     return true; 
    if (Object.ReferenceEquals(l, null) || Object.ReferenceEquals(r, null)) 
     return false; 
    //actual equality checks 
    } 
    public static bool operator != (Point l, Point r) { 
    return !(l==r); 
    } 
} 
Cuestiones relacionadas