2010-05-27 8 views
5

Ich habe eine Klasse in C# mit einer Vorlage und statischer Methode ähnlich wieerstellen Allgemeine Klasse Instanz von Statische Methode in einer abgeleiteten Klasse

class BClass<T> 
{ 
    public static BClass<T> Create() 
    { 
    return new BClass<T>(); 
    } 
} 

Daraus ich eine Klasse ableiten und einen Template-Parameter auf die Basisklasse angeben

class DClass : BClass<int> { } 

Ein Problem tritt auf, wenn ich die statische Methode zu verwenden versuchen, eine Instanz von D

class Program 
{ 
    static void Main(string[] args) 
    { 
    DClass d = DClass.Create(); 
    } 
} 
zu erstellen 0

Gibt einen Compiler-Fehler "Kann den Typ 'Test.BClass < int>' nicht zu 'Test.DClass' implizit konvertieren."

Das Hinzufügen der unten stehenden Umwandlung führt zu einer Ausnahme für das Ausführen von Castings.

Gibt es irgendeine Möglichkeit, die statische Methode Instanzen der abgeleiteten Klasse zu erstellen? Im Idealfall möchte ich das Äquivalent eines C++ Typedef und ich möchte nicht die folgende Syntax (die funktioniert).

BClass<int> d = DClass.Create(); 

Antwort

5

Ja, es ist möglich, von selbst auf die Art eine Art Referenz aufweist. Beachten Sie, dass es sich in der .NET-Welt um Generika handelt und nicht um Templates, bei denen die Funktionsweise sehr unterschiedlich ist.

class BClass<T, TSelf> where TSelf: BClass<T, TSelf>, new() { 
    public static TSelf Create() { 
     return new TSelf(); 
    } 
} 

class DClass: BClass<int, DClass> {} 

class Program { 
    static void Main(string[] args) { 
     DClass d = DClass.Create(); 
    } 
} 
+0

Dachte nicht, eine Klasse selbst als Typ-Parameter in seiner übergeordneten Klasse verweisen könnte? Paradox Huhn-Ei oder so ... –

+0

Clever UND ein bisschen bizarr! ;) Der einzige Nachteil, den ich hier sehe, ist, dass es scheint, dass es nie eine Möglichkeit geben würde, eine einfache alte 'BClass ' zu instanziieren, wie im ursprünglichen Code des OP. –

+0

@Peter, ich habe das tatsächlich ziemlich oft benutzt. Zum Beispiel erlaubt es Ihnen auch, eine bessere Klon-Methode zu erstellen, weil es das Neuschreiben usw. überflüssig macht. – Lucero

7

Es scheint, dass das, was Sie wollen, ist für DClass ein Alias ​​für BClass<int> zu sein. Aber das hast du hier nicht. Was Sie haben, ist, dass DClassvonBClass<int> abgeleitet wird. So ruft DClass.Create(); eine BClass<int>, die ist nicht eine DClass (es ist der umgekehrte Weg).

Dies könnte es klarer machen. Angenommen, Sie diese Hierarchie hatte:

class Rectangle { 
    static Rectangle Create() { 
     return new Rectangle(); 
    } 
} 

class Square : Rectangle { } 

// code elsewhere 
var shape = Square.Create(); // you might want this to return a square, 
          // but it's just going to return a rectangle 

Eine Möglichkeit so etwas wie die Funktionalität, die Sie erhalten möchten könnte es sein, Ihre Create Methode wie folgt zu definieren:

static TClass Create<TClass>() where TClass : BClass<T>, new() { 
    return new TClass(); 
} 

// code elsewhere 
var shape = DClass.Create<DClass>(); 

, die ein bisschen chaotisch, aber (und auch erfordert dass Sie einen parameterlosen Konstruktor für DClass schreiben). Wenn Sie eine Instanz Create für die Instanziierung Ihrer Objekte verwenden möchten, sollten Sie eine Factory-Klasse dafür schreiben.

1
class BClass<T> 
    { 
     public static T1 Create<T1, T2>() where T1 : BClass<T2>, new() 
     { 
      return new T1(); 
     } 
    } 

    class DClass : BClass<int> { } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      DClass d = DClass.Create<DClass, int>(); 
     } 
    } 
Verwandte Themen