2011-06-06 27 views
8

Estoy seguro de que esta es una pregunta estúpida, pero ¿por qué el siguiente código no llama al operador explícito para el molde en la clase hija MyBool?C# Operadores Explícitos y Herencia

public class DataType 
{ 
    public static explicit operator bool(DataType D) 
    { 
     return false; 
    } 

    public static explicit operator DataType(bool B) 
    { 
     return new DataType(); 
    } 
} 

public class MyBool : DataType 
{ 
    public bool Value; 

    public MyBool() 
    { 
     Value = false; 
    } 

    public static explicit operator bool(MyBool B) 
    { 
     return B.Value; 
    } 

    public static explicit operator MyBool(bool B) 
    { 
     return new MyBool() { Value = B }; 
    } 
} 

a continuación:

List<DataType> Types = new List<DataType>(); 

Types.Add(new MyBool() { Value = true }); 
Types.Add(new MyBool() { Value = false }); 

foreach (DataType T in Types) 
{ 
    bool Value = (bool)T; 
    MessageBox.Show(Value.ToString()); 
} 

produce la salida: falsa, falsa

es mi única opción para escribir funciones en cada clase para tomar el lugar de las funciones de operador explícitas?

+0

funciona igual que espera. – leppie

+1

Mi pregunta era "¿por qué el siguiente código no llama al operador explícito ...?" no "¿está funcionando correctamente?". – Andy

Respuesta

15

¿por qué el siguiente código no llama al operador explícito para el molde en la clase hija MyBool?

Debido a que las funciones de operador son static, por tanto, también no virtual y por lo tanto su objetivo se resuelve en tiempo de compilación en lugar de tiempo de ejecución. Este es el comportamiento esperado.

Si usted quiere tener los operadores de conversión polimórfica puede llamar a funciones virtuales dentro los operadores:

public abstract class DataType 
{ 
    public static explicit operator bool(DataType D) 
    { 
     return D.DoCastToBool(); 
    } 

    public static explicit operator DataType(bool B) 
    { 
     // We haven’t got an instance of our class here. 
     // You can use a factory method pattern to emulate virtual constructors. 
    } 

    protected abstract bool DoCastToBool(); 
} 
2

operadores están sobrecargado en lugar de anulados - en otras palabras, la decisión acerca de qué aplicación para usar se hace en en tiempo de compilación. El compilador solo conoce T como DataType, por lo que llama al operador en DataType.

Una opción sería eliminar al operador de MyBool, además de añadir un método virtual en DataType, teniendo en cuenta el comportamiento polimórfico:

public class DataType 
{ 
    public static explicit operator bool(DataType D) 
    { 
     // TODO: Decide how you want to handle null references 
     return D.ToBoolean(); 
    } 

    protected virtual bool ToBoolean() 
    { 
     return false; 
    } 
} 

public class MyBool : DataType 
{ 
    // ... 

    protected override bool ToBoolean() 
    { 
     return Value; 
    } 
} 

Tenga en cuenta que esta voluntad no trabajo para la conversión de bool a a DataType, como en ese caso no tenemos ninguna información sobre qué subtipo de DataType realmente desea crear.

(Side-nota:. Su código sería más fácil de seguir si utilizó las convenciones normales de nombres .NET)

+0

Jon, ¿este ha sido siempre el caso en las versiones de .NET? ¿O ha habido un momento en que .NET buscó jerarquías de herencia? Lo pregunto porque un error relacionado con esto parece coincidir con una actualización del proyecto a un .NET más nuevo. El objeto en cuestión se escribe como 'objeto' en tiempo de compilación, pero el tipo de tiempo de ejecución tiene definido el operador. Dudo mucho que este sea el caso, pero se ha sugerido ... – Sprague

+1

@Sprague: No, siempre ha sido así. –