2010-05-27 8 views
5

Ho una classe in C# con un modello e metodo statico simile aCrea Generic Class grado dal Metodo statico in una classe derivata

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

Da questo ho derivare una classe e specificare un parametro di modello per la classe di base

class DClass : BClass<int> { } 

un problema si verifica quando si tenta di utilizzare il metodo statico per creare un'istanza di D

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

Segnala un errore del compilatore "Impossibile convertire implicitamente il tipo 'Test.BClass < int>' in 'Test.DClass'."

Aggiunta dei seguenti lead cast a un'eccezione di esecuzione runtime.

DClass d = (DClass)DClass.Create(); 

C'è qualche modo per consentire al metodo statico di creare istanze della classe derivata? Idealmente mi piacerebbe l'equivalente di un typedef C++ e non voglio la sintassi qui sotto (che funziona).

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

risposta

5

sì è possibile, avendo un tipo di riferimento al tipo stesso. Si noti che nel mondo .NET stiamo parlando di generici, non di modelli, che hanno importanti differenze nel modo in cui funzionano.

+0

Non pensavo che una classe potesse fare riferimento a se stessa come parametro di tipo nella sua superclasse? Pollo e uovo paradosso o qualcosa del genere ... –

+0

Intelligente E un po 'bizzarro! ;) L'unico svantaggio che vedo qui è che sembra che non ci sarebbe mai stato alcun modo per istanziare un semplice vecchio 'BClass ', come nel codice originale dell'OP. –

+0

@Peter, in realtà l'ho usato con successo parecchio. Ad esempio, consente anche di creare un metodo di clonazione migliore perché elimina la necessità di eseguire nuovamente il cast, ecc. – Lucero

7

Sembra che ciò che si vuole è per DClass di essere un alias per BClass<int>. Ma non è quello che hai qui. Quello che hai è che DClassderiva daBClass<int>. Chiamando così DClass.Create(); crea un BClass<int>, che è non a DClass (è il contrario).

Ciò potrebbe rendere più chiaro. Supponiamo che hai avuto questa gerarchia:

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 

Una possibilità per ottenere qualcosa di simile alla funzionalità desiderata potrebbe essere quella di definire il metodo di Create in questo modo:

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

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

Questo è un po 'confuso, anche se (e richiede anche che si scrive un costruttore senza parametri per DClass). Se sei morto impostato sull'utilizzo di un metodo Create per l'istanziazione dei tuoi oggetti, considera di scrivere una classe factory per questo.

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