2009-07-15 11 views
1

Ich versuche, eine generische Schnittstelle zu erstellen, die die System.ICloneable-Schnittstelle erbt, aber der Rückgabewert der Clone() - Methode ist T. Natürlich benötigt der T-Typ Einschränkungen um sicher zu gehen, dass es eine Vererbung der System.Object-Klasse ist, aber der folgende Code nicht funktioniert.Geben Sie Parametereinschränkungen für das Liskov-Prinzip in C# ein. .NET

public interface ICloneable<T> : System.ICloneable where T : object { 

    T Clone(); 

} 

Was mache ich falsch?

Auch die folgenden Einschränkungen funktionieren nicht:

  1. where T: System.Object
  2. where T: Klasse

wie kann ich das Liskov-Prinzip in diesem Fall verwenden, die sagt, dass Sie Ihren Rückgabetyp einschränken können, um dieses Problem zu lösen?

P.S .: Sorry für mein Englisch, wenn ich Fehler gemacht habe. Ich bin kein englischer Muttersprachler.

+1

Keine Entschuldigung für Ihr Englisch, es ist in Ordnung. –

+0

Übrigens würde ich vorschlagen, dass Sie den Typ T als Kovariante markieren (setzen Sie das Wort "out" davor) und fügen Sie entweder eine schreibgeschützte Eigenschaft "T self" hinzu, oder definieren Sie eine Schnittstelle ISelf mit einem schreibgeschützten Eigenschaft "T selbst". Beachten Sie, dass T nicht auf ICloneable oder ISelf beschränkt sein sollte. Wenn Sie dies tun, können Sie die Klassen Foo und DerivedFoo ohne öffentliche Klonmethode und die Klassen CloneableFoo und CloneableDerivedFoo verwenden, die von diesen abgeleitet sind und jedes klonbare Derivat von Foo als ICloneable akzeptieren, obwohl solche klonbaren Derivate keine gemeinsame Basisklasse teilen . – supercat

Antwort

5

Warum brauchen Sie überhaupt eine Einschränkung? Alles erbt von object ...

Ohne Einschränkung sollte Ihr Code arbeiten, aber Sie werden beide Clone Methoden in der gleichen Weise wie IEnumerable/IEnumerable<T> Arbeit implementieren müssen - .NET muss nicht kovarianten Rückgabetypen. Sie sollten auch dann angeben, dass Ihr Clone Methode die man in ICloneable versteckt:

public interface ICloneable<T> : ICloneable 
{ 
    new T Clone(); 
} 

Beachten Sie, dass die aktuelle ICloneable Schnittstelle etwas veraltet ist - weil es keinen Hinweis auf die Tiefe des Klonens gibt, ist es nicht besonders nützlich in den meisten Fälle.

Müssen Sie wirklich den nicht-generischen Typ überhaupt erweitern? Erwarten Sie, dass Benutzer die nicht-generische Schnittstelle sowie Ihre generische Schnittstelle verwenden möchten?

+0

Ich möchte eine Schnittstelle, also muss ich die Clone() - Methode nur einmal schreiben. Also ohne es für System.ICloneable.Clone() neu zu schreiben. Und ich muss nur die ICloneable -Schnittstelle implementieren. Ohne Methoden zu schreiben, die durch diese Methode verdeckt werden. –

+1

In diesem Fall würde ich jede Referenz auf die nicht-generische Schnittstelle entfernen, und ohne die Einschränkung sollten Sie in Ordnung sein. –