Frage

Wenn ich mit expliziten Schnittstellenimplementierungen in C # arbeite, wird es oft notwendig, um ein Objekt zu einem seiner Schnittstellen, um warf ein Mitglied dieser Schnittstelle zuzugreifen. Aufgrund der verbesserten Zuverlässigkeit und Wartbarkeit durch Kompilierung Typüberprüfung ergab, ich habe immer zu verwenden implizite Konvertierungen bevorzugt diese auszuführen. Der einzige Weg, ich weiß, dies zu tun, besteht aus zwei Zeilen Code und stellt eine weitere Variable in den Anwendungsbereich. Im Folgenden finden Sie ein Beispiel:

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

Da der Compiler weiß , dass MyType Geräte IMyType Ich gehe davon aus, dass eine implizite Umwandlung besser ist als eine explizite ein, da eine nachträgliche Änderung der Erklärung des MyType in einem Compiler-Fehler führen wird anstelle eines InvalidCastException bei Laufzeit. Allerdings habe ich etwas die Einfachheit der expliziten Umwandlung Syntax bevorzugen und habe oft es in anderen Leuten Code verwendet gesehen.

Meine Frage ist dreifach:

  • Welche der oben genannten Optionen bevorzugen Sie (und warum)?
  • Gibt es einen besseren Weg, dies zu tun?
  • Was einige Best Practices sind in Bezug auf explizite Casts durchzuführen, wenn implizite Abgüsse sind möglich?
War es hilfreich?

Lösung

Hier ist eine Kompilierung-Einzeiler geprüft:

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

Andere Tipps

Als Antwort auf alle drei Fragen: Verlassen Sie sich auf implizite Abgüsse als allgemeine Regel. Sie sind Programmierung gegen die Schnittstelle, nicht die Umsetzung.

Wie für die letzte, wenn Sie wirklich auf die Programmierung gegen eine Implementierung (eine bestimmte abgeleitete Klasse) verlassen müssen, dann stellen Sie sicher, dass das Objekt kann den Typ umgewandelt werden, bevor irgendetwas damit zu tun. So etwas wie folgt aus:

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

Wenn Sie nicht sicher sind, dass das Objekt eine Instanz der Schnittstelle tut dann eine als / null zu überprüfen. Normalerweise sind Sie eine Schnittstelle von einer Methode / Funktionsaufruf zurückkehrt, in dem Fall, dass Sie speichern Sie es nur in einer Variablen ohne Guss (obwohl die Nullprüfung noch erforderlich sein kann).

Ich mag es in der Regel als:

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

     }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top