Frage

Bedenken Sie:

public class interface Person : IPerson
{
  int ID { get; protected set; }
  string FirstName { get; set; }
  string LastName { get; set; }
  string FullName { get { return FirstName + " " + LastName; } }
}

Und dies:

public class StubPerson : IPerson
{
    int ID { get { return 0; protected set { } }
    string FirstName { get { return "Test" } set { } }
    string LastName { get { return "User" } set { } }
    string FullName { get { return FirstName + " " + LastName; } }
}

Verbrauch:

IPerson iperson = new Person();

Oder:

IPerson ipersonStub = new StubPerson();

Oder:

IPerson ipersonMock = mocks.CreateMock<IPerson>();

Also in der Tat sind wir erklären die IPerson Schnittstelle und die Person Klasse zur gleichen Zeit:

public class interface Person : IPerson

Glauben Sie, es wäre nützlich, diese Art von Unterstützung in .NET / C # haben?

Edit:

Durch Massenverwirrung Ich glaube, ich brauche den vorgeschlagenen Zweck zu klären:

Ohne diese Funktion würden Sie schreiben müssen:

interface IPerson
{
  int ID { get; }
  string FirstName { get; set; }
  string LastName { get; set; }
  string FullName { get; }
}

als auch diese:

public class Person : IPerson
{
  int ID { get; protected set; }
  string FirstName { get; set; }
  string LastName { get; set; }
  string FullName { get { return FirstName + " " + LastName; } }
}

Ich schlage keine semantische Veränderung.

War es hilfreich?

Lösung

Ich betrachtete die gleiche Art der Sache vor einer Weile , insbesondere für die Verwendung in dem Fall, dass Sie nur eine Produktions Implementierung einer Schnittstelle haben, aber Sie wollen, dass es verspotten zum Testen. Im Moment endet es ist ein bisschen wie die .c / h-Dateien von alten Zeiten auf.

Ich vermute, dass am Ende, dass die Vorteile der es durch die zusätzliche Komplexität aufgewogen werden sowohl in der Sprache und dann den Code später zu lesen. Ich würde immer noch daran interessiert sein zu sehen, es gründliche obwohl erforscht. Selbst dann gibt es andere Dinge viel höher auf meiner Prioritätenliste - eine bessere Unterstützung für Unveränderlichkeit an der Spitze zu sein:)

Andere Tipps

Lassen Sie mich sehen, ob ich verstehe, was Sie fragen:

Warum können wir nicht erklären, eine Schnittstelle:

interface IPerson
{
    string Name {get;set;}
    int ID {get;set;}
}

Und Klassen, die diese Schnittstelle implementieren, um seine Eigenschaften erben, ohne sie neu zu deklarieren:

class Person : IPerson { } 
//person now has properties Name and ID

Der Grund, warum Sie nicht tun können, ist dies, obwohl der Text Ihres Interface-Code und Ihren Klassencode ist sehr ähnlich, sie bedeuten sehr verschiedene Dinge. Die Schnittstelle sagt einfach „Implementierer einen String-Name mit Getter und Setter haben wird“. Es ist die Klasse, die sagt, dass „privates Feld zurück, wenn Getter für Namen aufgerufen wird.“ Selbst wenn Sie die Auto-Eigenschaft Verknüpfung verwenden die Compiler zu lassen, dass die Logik implementieren, ist es immer noch Logik , die in der Klasse gehört. Nur weil:

string Name {get;set;}

sieht das gleiche in einer Schnittstelle und in einer Klasse, bedeutet es nicht, auch nur annähernd die gleiche Sache.

Es wäre sehr gefährlich für die Compiler beliebige Logik implementieren Ihre Verträge für Sie zu erfüllen, anstatt bei der Kompilierung zu beklagen, dass Sie sie nicht umgesetzt haben. Es könnte einführen Fehler nur sehr schwer aufzuspüren. Compiler Mit zurückgreifen Verhalten auf Standard wenn kein Verhalten definiert wird, ist eine sehr, sehr schlechte Idee.

Ich glaube, Eiffel tut so etwas wie dies auf .NET, um Mehrfachvererbung zu unterstützen. Eine Klassendeklaration automatisch eine entsprechende Schnittstelle. Wenn der Klassentyp bezeichnet wird, gibt der Compiler meist ein Verweis auf die anstelle Schnittstelle eingeben. Die wichtigste Ausnahme ist in Konstruktor Ausdrücke natürlich.

Nun, ich denke die anderen Antworten helfen Ihnen die Nutzung der Schnittstelle zur abstrakten Logik in verschiedenen konkreten Klassen zu verstehen, ich denke auch Sie etwas ähnliches erreichen, was Sie wollen die Refactoring-Tools in VS gebaut werden.

Ihre Klasse definieren ...

public class Person
{
  public int ID { get; protected set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string FullName { get { return FirstName + " " + LastName; } }
}

Dann mit der rechten Maustaste, wählen Umgestalten. -> Interface extrahieren

Dies wird eine separate Datei enthält die Schnittstelle für die Definition der Klasse erstellen, könnten Sie dann die Schnittstelle formen und implementierenden Klassen entsprechend.

Extrahiert Schnittstelle:

interface IPerson
{
    string FirstName { get; set; }
    string FullName { get; }
    int ID { get; }
    string LastName { get; set; }
}

Ich glaube, ich den Punkt bin fehlt - was erreichen Sie durch eine Klasse Mischen und eine Schnittstelle zusammen? Welches Problem Sie mit diesem Ansatz lösen?

Dieses:

IPerson iperson = new Person();

ist bereits legal in C #.

Edit: Zur Verdeutlichung - der Code oben ist legal angesichts der folgenden:

interface IPerson { }

class Person : IPerson { }

Ich würde zumindest wie Visual Studio zu meinen Eigenschaften von einer Schnittstelle als Auto Eigenschaften zu implementieren, wenn ich es beantragen, dies zu tun.

Leider funktioniert diese Option nicht, und ich habe mit Nicht implementiert Ausnahme Stubs behandeln

Nein, weil man gezwungen wäre, alle öffentlichen Mitglieder einer Schnittstelle zu belichten. Versuchen Sie ReSharper und nie Sorgen um diese wieder.

ReSharper kann diese Funktionalität bereitstellen, z. B.

  1. Sie können Ihre Klasse Person schreiben zuerst.
  2. Sie können Ihre Schnittstelle von extrahieren Mitglieder bis die Zieh IPerson Schnittstelle.

Folglich können Sie Visual Studio haben Implementierung Stubs für Sie automatisch generieren.

UPDATE

Wie auch immer, lassen Sie uns zuerst über Schnittstellen auslegen, unter Berufung auf den Code Sie in Ihrer Frage zu finden:

public class interface Person : IPerson
{
    int ID { get; protected set; }
    string FirstName { get; set; }
    string LastName { get; set; }
    string FullName { get { return FirstName + " " + LastName; } }
}

Sie müssen verstehen, dass eine Schnittstelle nicht eine abstrakte Klasse ist. Eine Schnittstelle ist nur ein Vertrag , ein Entwurf der Art, was bedeutet, dass es ein Objekt sagen, was ohne wirklich die Sorge um in einem anderen Objekt zu erwarten, wie es umgesetzt wird.

Eine abstrakte Klasse, auf der anderen Seite kann Auszüge Funktionalität enthält, die vererbt werden können und außer Kraft gesetzt.

Im obigen Fall Ihre „Schnittstelle“ ist ungültig, weil:

  • Sie konnte nicht Umfang Einschränkungen für Schnittstellen (öffentlich, privat, geschützt, intern), wie das ist eine Implementierung Detail
  • erklären
  • Sie nicht eine Standardimplementierung erklären könnten (zum Beispiel Ihrer FullName Eigenschaft), weil wieder, das ist eine Implementierung Detail

Es scheint mir, was Sie wirklich wirklich wollen, ist eine abstrakte Klasse, z. B.

public abstract class BasePerson
{
    public abstract int ID { get; protected set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public virtual string FullName { get { return FirstName + " " + LastName; } } 
}

Ich kann nur raten, aber vielleicht ist das, was Sie wirklich brauchen.

UPDATE 2

Okay, ich glaube, ich bin immer an, was Sie wollen passieren, so was Sie wollen in der Lage sein, dies zu schreiben:

public interface IPerson
{
    int ID { get; set; }
    string FirstName { get; set; }
    string LastName { get; set; }
    string FullName { get; }
}

Und dann für Ihre Implementierung nur brauchen, dies zu schreiben:

public class Person : IPerson
{
    public int ID { get; protected set; }
    public string FullName { get { return FirstName + " " + LastName; } } 
}

, ohne die Vor- und den Nachnamen Eigenschaften angeben.

Das erste Problem, das wir angehen müssen, ist die Tatsache, dass Schnittstellen Zugriff erlauben keine Trennzeichen in der Umsetzung. Was passieren würde, ist, dass die Eigenschaften der Standardzugriffs Begrenzer erben würde, was privat ist

Zweitens ist die Tatsache, dass, während in unseren Augen string FirstName { get; set; } in einer Schnittstelle und public string FirstName { get; set; } in einer Klasse gleich sind, sind sie eigentlich nicht:

  • in einer Schnittstelle, wird die Eigenschaft Definition zeigen, dass die Methodensignaturen für die Getter und / oder Setter-Methoden werden für alle Klassen zur Verfügung, die eine Schnittstelle zu implementieren.
  • in einer Klasse, wird die Eigenschaftsdefinition des CLR anweisen ein anonymes Objekt zu erstellen, die den Wert des Eigentums halten werden.

Subtle Unterschied für den Programmierer, Welten auseinander für den Compiler.

Schließlich, wenn Sie angeben, dass Sie eine Schnittstelle implementieren, funktioniert Visual Studio synctactic zaubern, die diese Eigenschaft Stubs automatisch für Sie macht.

Ich denke, eine bessere Abstraktion für dieses eine Eigenschaft ist, oder, wie ich beschrieben habe, hier , eine Rolle. Das ist wie eine Schnittstelle mit dem Code. Ihr Beispiel wie folgt codiert werden:

public role RPerson { 
  int ID { get; protected set; } 
  string FirstName { get; set; } 
  string LastName { get; set; } 
  string FullName { get { return FirstName + " " + LastName; } } 
} 

public class Person : RPerson { }

public class StubPerson : RPerson { 
    int ID { get { return 0; protected set { } } 
    string FirstName { get { return "Test" } set { } } 
    string LastName { get { return "User" } set { } } 
    string FullName { get { return FirstName + " " + LastName; } } 
} 

// ...

RPerson rperson = new Person(); 

RPerson rpersonStub = new StubPerson(); 
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top