2013-08-08 14 views
10

Qui abbiamo una semplice herarchy classe, e l'uso di farmaci generici con un type constraint di new()tipo di vincolo generico di nuovo() e una base astratta classe

public abstract class Base 
{ 
} 

public class Derived : Base 
{ 
} 

public class TestClass 
{ 
    private void DoSomething<T>(T arg) where T : new() 
    { 
    } 

    public void TestMethod() 
    { 
     Derived d1 = new Derived(); 
     DoSomething(d1); // compiles 

     Base d2 = new Derived(); 
     DoSomething(d2); // compile error 
    } 
} 

Il codice fallisce la compilazione alla linea indicata con un errore di:

'Base' deve essere un tipo non astratta con un costruttore senza parametri pubblico al fine di utilizzarlo come parametro 'T' nel tipo generico o il metodo 'Foo.DoSomething (T)'

Questo errore è chiaro e ha senso, ma speravo che il compilatore avrebbe capito che tutte le derivazioni di Base (che potrebbero essere istanziate a questo punto) hanno un costruttore pubblico senza parametri.

Questo sarebbe teoricamente possibile per il compilatore?

+0

È questa linea che mi preoccupa di più di "tipo non astratto" rispetto alla clausola del costruttore senza parametro –

risposta

8

Ahimè si deve dare esplicitamente il tipo

DoSomething<Derived>(d2); 

teoricamente non è possibile creare qualcosa che sia astratta

+5

Mi piace la parte "teoricamente". Mi fa sentire come se apparisse Jon Skeet, fare un po 'di magia, e ci sei, oggetto astratto istanziato. –

+0

Su quale versione di .NET viene compilato se d2 è dichiarato come Base astratta? –

1

new Constraint (C# Reference):

Per utilizzare il nuovo vincolo, il tipo non può essere astratto.

Calling:

Base d2 = new Derived(); 
DoSomething(d2); 

si sono infatti fare:

Base d2 = new Derived(); 
DoSomething<Base>(d2); 

Dal momento che l'Base è astratta, si verifica un errore di compilazione.

Quindi, bisogna lanciare in modo esplicito:

Base d2 = new Derived(); 
DoSomething((Derived) d2); 

Come hai potuto garantire il compilatore, che nessuno mai ci ha messo qualcosa, che non è astratta?

L'unico modo che vedo sarebbe, se avessimo una parola chiave come "must-inherit-to-non-astract" e quindi creare public must-inherit-to-non-abstract abstract class Base. Dopo di ciò, il compilatore potrebbe essere sicuro, che se si inserisce l'istanza di base nel proprio metodo, questa sarà di fatto una sottoclasse, che non è astratta e quindi può essere istanziata.

Problemi correlati