Question

Quand je travaille avec des implémentations d'interface explicites en C #, il devient souvent nécessaire de jeter un objet à l'une de ses interfaces afin d'accéder à un membre de cette interface. En raison de l'amélioration de la fiabilité et la maintenabilité offerte par la compilation vérification du type de temps, je l'ai toujours préféré utiliser les conversions implicites pour effectuer cette. La seule façon que je connaisse pour faire cela implique deux lignes de code et introduit une autre variable dans le champ d'application. est un exemple ci-dessous:

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());
    }
}

Parce que le compilateur sait que MyType outils IMyType Je suppose qu'un casting implicite est mieux qu'un explicite car un changement plus tard à la déclaration de MyType entraînera une erreur de compilation au lieu d'un InvalidCastException à Durée. Cependant, je préfère un peu la simplicité de la syntaxe explicite coulé et ai souvent vu utilisé dans le code des autres.

Ma question est triple:

  • Laquelle des options ci-dessus ne vous préférez (et pourquoi)?
  • Y at-il une meilleure façon de le faire?
  • Quelles sont les meilleures pratiques en ce qui concerne l'exécution des moulages explicites lorsque des conversions implicites sont possibles?
Était-ce utile?

La solution

Voici une compilation vérifié une doublure:

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();
    }
}

Autres conseils

En réponse à trois questions: Fiez-vous à des conversions implicites en règle générale. Vous programmons contre l'interface, pas la mise en œuvre.

En ce qui concerne le dernier, si vous devez vraiment compter sur la programmation contre une mise en œuvre (une classe dérivée spécifique), alors assurez-vous que l'objet peut être jeté type avant d'essayer de faire quoi que ce soit avec lui. Quelque chose comme ceci:

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

Si vous n'êtes pas sûr que l'objet est une instance de l'interface, puis faire une vérification comme / null. En général, vous retournez une interface à partir d'une méthode / appel de fonction dans ce cas, vous stockez juste dans une variable sans casting (bien que le chèque nul peut encore être nécessaire).

Je habituellement comme comme:

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... */ }

     }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top