2010-02-03 10 views
7

Un collega mi ha indirizzato verso uno strano caso in C# (non è sicuro se questo sia davvero strano).
Supponiamo di avere un dipendente di classe. Se si desidera creare un elenco generico <> di tipo Employee, si può semplicemente fare:
Perché questo non è possibile in C# Generics?

List<Employee> x = new List<Employee>; 

ho capito che ho bisogno di passare il tipo Employee alla lista generico in modo che conosce le informazioni tipo richiesto su Dipendente e genera metodi che restituiscono e accettano parametri compatibili con Dipendente.

Ora la mia domanda è: perché non è possibile eseguire quanto segue?

Employee x = new Employee(); 
List<typeof(x)> list = new List<typeof(x)>(); 

Non dovrebbe bastare questo le informazioni necessarie per Lista <> di conoscere, al fine di creare una lista? In altre parole, il tipo di x che è il tipo di Dipendente è ora passato come parametro di tipo generico a Elenco <>, che (come credevo) è lo stesso della lista di passaggio il nome del tipo (in questo caso Dipendente) .

So che qualcosa di simile è disponibile in Java (utilizzando la parola chiave .class) su una variabile.

Sono sicuro che mi manca qualcosa, quindi per favore, illuminami ragazzi!

risposta

30

No, l'equivalente di quello non è disponibile in Java. Non è possibile utilizzare "x.class" per ottenere il tipo dichiarato di una variabile.

Inoltre, typeof(x) non funziona in C# sia per ottenere il tipo di una variabile - restituisce un riferimento Type per il nome tipo, per esempio typeof(string) restituirà un riferimento all'oggetto Type associato al tipo System.String. È equivalente all'utilizzo di String.class in Java. (Si noti che ancora una volta, che è l'applicazione di .class ad un nome di tipo, non un nome di variabile.) Generici

Java non supportano nulla di simile la sua dichiarazione finale sia. Se credi che fanno, si prega di fornire un campione :)

Cosa si può fare in C# è di tipo uso di inferenza di fare ciò che si vuole:

public static List<T> CreateListForSampleType<T>(T sample) 
{ 
    return new List<T>(); 
} 

... 

Employee x = new Employee(); 
var list = CreateListForSampleType(x); 

Nota che non c'è alcun motivo per cui C# couldn 't essere esteso per consentire qualcosa come typeof(variablename) o List<typeof(variablename)> - è tutto il tipo di informazioni in fase di compilazione, dopo tutto. Tuttavia, non vedo che soddisfi i requisiti della squadra per l'utilità ... ci sono altre funzionalità molto più utili che mi piacerebbe vedere prima :)

+1

Esempio di buon codice. Cosa succederebbe se si usasse 'typeof' nella variabile' list'? – FrustratedWithFormsDesigner

+1

typeof (elenco) comporterebbe un errore di compilazione. –

+0

Jon, grazie per la tua risposta dettagliata! E poiché si tratta di informazioni sulla compilazione del tempo, allora sono sulla strada giusta. Parlare del fatto che sia utile o meno è in qualche modo controverso;). – Galilyou

2

Il motivo è che typeof() restituisce un digita oggetto, mentre è necessario un nome di tipo per inizializzare una lista in fase di compilazione.

1

typeof viene utilizzato con i nomi di classe. Utilizzare GetType() su un oggetto, ma solo in fase di esecuzione ...

2

Una parte della risposta è che il tipo di x non è disponibile in fase di compilazione, ad es.potrebbe essere creato utilizzando qualcosa di simile:

Employee x = EmployeeFactory.NewEmployee("John Doe"); // Returns TraineeEmployee, Employee or ManagementEmployee; 

List<typeof(x)> l = new List<typeof(x)> l(); // What type is it? 

È possibile comunque creare un elenco di una classe base di ciò che si desidera memorizzare nella lista (o anche di un elenco di s "oggetto").

1

Quello che ti manca - imho - è la differenza tra un riferimento di tipo statico in fase di compilazione e un riferimento al tipo dinamyc (tramite un'istanza di System.Type) in fase di esecuzione.

typeof() e .GetType() forniscono quest'ultimo. (per tipi e istanze, rispettivamente)

Spero che sia chiaro.

Il codice di Jon Skeet sopra è bello.

0

Impossibile trovare un motivo per creare una lista vuota da C# 3.0.

Generalmente creare istanze lista soltanto con un metodo ToList da un IEnumerable, che è a sua volta generato utilizzando un ritorno rendimento, Concat(), Repeat(), dove() ecc

var list = CreateEmployees().ToList(); 

,

public IEnumerable<Employee> CreateEmployees() 
{ 
yield return new Employee("Foo"); 
yield return new Employee("Bar"); 
} 
Problemi correlati