Pregunta

Cuando estoy trabajando con implementaciones de interfaces explícitas en C #, a menudo se hace necesario convertir un objeto a una de sus interfaces con el fin de acceder a un miembro de esa interfaz. Debido a la mayor fiabilidad y facilidad de mantenimiento proporcionada por la comprobación de tipos en tiempo de compilación, siempre he preferido utilizar conversiones implícitas para realizar esto. La única forma que conozco de hacer esto consiste en dos líneas de código e introduce otra variable en el ámbito de aplicación. A continuación se muestra un ejemplo:

public interface IMyType
{
    string SayHello();
}

public class MyType : IMyType
{
    string IMyType.SayHello() { return "Hello!"; }
}

class Program
{
    static void Main(string[] args)
    {
        var item = new MyType();

        // Option 1 - Implicit cast. Compile time checked but takes two lines.
        IMyType item2 = item;
        System.Console.WriteLine(item2.SayHello());

        // Option 2 - One line but risks an InvalidCastException at runtime if MyType changes.
        System.Console.WriteLine(((IMyType)item).SayHello());

        // Option 3 - One line but risks a NullReferenceException at runtime if MyType changes.
        System.Console.WriteLine((item as IMyType).SayHello());
    }
}

Debido a que el compilador sabe que implementa MyType IMyType Asumo que una conversión implícita es mejor que una explícita ya que un cambio posterior a la declaración de MyType dará lugar a un error de compilación en lugar de un InvalidCastException en tiempo de ejecución. Sin embargo, yo prefiero un poco la simplicidad de la sintaxis conversión explícita y, a menudo he visto que se usa en el código de otras personas.

Mi pregunta es triple:

  • ¿Cuál de las opciones anteriores prefiere (y por qué)?
  • ¿Hay una mejor manera de hacer esto?
  • ¿Cuáles son algunas de las mejores prácticas con respecto a la realización de conversiones explícitas cuando son posibles conversiones implícitas?
¿Fue útil?

Solución

Aquí es un tiempo de compilación comprueba un trazador de líneas:

public static class Converter
{
    public static T ReturnAs<T>(T item)
    {
        return item;
    }
}


class Program
{
    static void Main(string[] args)
    {
        var item = new MyType();

        // Option 1 - Implicit cast. Compile time checked but takes two lines.
        IMyType item2 = item;
        System.Console.WriteLine(item2.SayHello());

        // Option 2 - One line but risks an InvalidCastException at runtime if MyType changes.
        System.Console.WriteLine(((IMyType)item).SayHello());

        // Option 3 - One line but risks a NullReferenceException at runtime if MyType changes.
        System.Console.WriteLine((item as IMyType).SayHello());

        // Option 4 - compile time one liner
        Converter.ReturnAs<IMyType>(item).SayHello();
    }
}

Otros consejos

Como respuesta a las tres preguntas: Se basan en conversiones implícitas como una regla general. Usted está programando en contra de la interfaz, no la implementación.

En cuanto a la última, si realmente debe confiar en la programación en contra de una aplicación (una clase derivada específica), entonces asegúrese de que el objeto se puede convertir el tipo antes de tratar de hacer nada con ella. Algo como esto:

var IMyType item3 = item as MyConcreteType;
if(item3 != null) {
    item3.SayHello();
}

Si no está seguro de que el objeto es una instancia de la interfaz y luego hacer un cheque como / null. Por lo general, usted está volviendo una interfaz de una llamada a un método / función en cuyo caso que acaba de almacenar en una variable sin una conversión (aunque el cheque nulo aún puede ser necesario).

normalmente me gusta como:

class Program
{
    static void Main(string[] args)
    {
        var item = new MyType();
        if( item is IMyType ){
          Console.WriteLine( (item as IMyType).SayHello() );
        }
        else { /* Do something here... */ }

     }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top