2016-10-03 4 views
-2

Ich versuche, ICloneable.Clone() in einer abstrakten Basisklasse zu implementieren, so dass Unterklassen sich nicht darum kümmern müssen. Eine grundlegende Verantwortung dieser Klasse besteht darin, eine interne Guid-Eigenschaft zu haben, die an die Klone weitergegeben werden sollte - das heißt, es ist eher ein "Eigenschaftsklon". Dadurch kann ich ein aus einem Repository entnommenes Objekt klonen, seine Eigenschaften ändern, ohne das ursprüngliche Element zu ändern, und anschließend die geänderte Instanz so an den Repo zurücksenden, dass sie anhand der ID erkannt werden kann.Benutzerdefinierte ICloneable-Implementierung in abstrakte Basisklasse einfügen

Aber meine aktuelle Implementierung steht vor einem Problem: Ich kann die Instanzen nicht erstellen, um die ID weiterzugeben, weil die Klasse abstrakt ist!

public abstract class RepoItem : ICloneable, IEquatable<RepoItem> 
{ 
    protected RepoItem() 
    { 
     Id = Guid.NewGuid(); 
    } 

    private RepoItem(Guid id) 
    { 
     Id = id; 
    } 

    public Guid Id { get; private set; } 

    public object Clone() 
    { 
     return new RepoItem(Id); // cannot create instance of abstract class 
    } 

    public bool Equals(RepoItem other) 
    { 
     return other.Id == Id; 
    } 
} 

Gibt es eine Möglichkeit, dieses Problem zu lösen? Ist das ein anständiges Design für den Anfang?

+2

Sie erstellen sowieso den falschen Typ. Und das Problem ist, Sie haben keine Ahnung, was der richtige Typ in der Basisklasse sein sollte. Sie müssen eine Instanz des tatsächlichen Laufzeittyps erstellen - z. durch eine abstrakte Methode, die die abgeleiteten Klassen implementieren werden. – Luaan

+1

Sie können auch einfach 'Clone' abstrahieren, weil die Kind-Klasse diejenigen sind, die sich klonen können. – juharr

+0

@Luaan Glaubst du, dass ein auf Reflexion basierender Ansatz ausreichen würde? – heltonbiker

Antwort

3

Machen Sie einen Schritt zurück. Sie sollten diese Schnittstelle überhaupt nicht implementieren, also ob die Implementierung in einer Basisklasse oder was auch immer ist völlig neben dem Punkt. Geh einfach nicht dorthin.

Diese Schnittstelle wurde seit 2003. Siehe veraltet:

Why should I implement ICloneable in c#?

für weitere Einzelheiten.

+0

Nun, ich denke, das war autoritativ genug; o) Danke !! – heltonbiker

0

Wie bereits in den Kommentaren erklärt, können Sie das nicht tun ...

Das Beste, was zu tun, wahrscheinlich Clone eine abstrakte Methode zu machen ist (um sicherzustellen, dass das Klonen für alle abgeleiteten Klassen zur Verfügung steht, obwohl man explizit muss überschreiben Clone, wenn die mehr als eine Ebene der Ableitung sind und mehr als eine Ebene hat eine class, die instanziiert werden kann.).

Danach, mit Art Copy-Konstruktor wäre der Weg zu gehen:

class RepoItem : ICloneable 
{ 
    public abstract void Clone(); 
    protected RepoItem(RepoItem other) { Id = other.Id; } 
} 

class Derived1 : RepoItem 
{ 
    protected Derived1(Derived1 other) : base(other) 
    { 
     myField1 = other.myField1; 
    } 
    public virtual object Clone() { return new Derived1(this); } 

    private int myField1; 
} 

class Derived2 : Derived1 
{ 
    protected Derived2(Derived2 other) : base(other) 
    { 
     myField2 = other.myField2; 
    } 
    public override object Clone() { return new Derived2(this); } 

    private int myField2; 
} 

Ich bin nicht sicher, ob ich bekam virtual und override Recht, wie ich selten einen solchen Code schreiben.

Verwandte Themen