2009-07-30 11 views
8

Eventuali duplicati:
What are the differences between Generics in C# and Java… and Templates in C++?C# generici rispetto ai modelli C++

Quali sono le differenze tra C# generici rispetto ai modelli C++? Capisco che non risolvono esattamente lo stesso problema, quindi quali sono i pro e i contro di entrambi?

+4

Che coincidenza, questo è il tema del mio blog per oggi. http://blogs.msdn.com/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx –

+1

questo * ha * ottenuto il duplicato esatto. @Eric Lippert: Ooh, interessante, gli darò una lettura – jalf

risposta

16

si può considerare modelli C++ per essere un linguaggio di programmazione funzionale, interpretato travestito da un sistema di farmaci generici. Se questo non ti spaventa, dovrebbe :)

I generici di C# sono molto limitati; puoi parametrizzare una classe su un tipo o tipi e usarli in metodi. Così, per fare un esempio da MSDN, si potrebbe fare:

public class Stack<T> 
{ 
    T[] m_Items; 
    public void Push(T item) 
    {...} 
    public T Pop() 
    {...} 
} 

E ora si può dichiarare una Stack<int> o Stack<SomeObject> e Sarà memorizzare oggetti di quel tipo, in modo sicuro (vale a dire, non preoccupato di mettere in SomeOtherObject da sbaglio).

Internamente, il runtime .NET lo specializzerà in varianti per i tipi fondamentali come int e una variante per i tipi di oggetto. Ciò consente alla rappresentazione di Stack<byte> di essere molto più piccola di quella di Stack<SomeObject>, ad esempio.

modelli C++ consentono un uso simile:

template<typename T> 
class Stack 
{ 
    T *m_Items; 
    public void Push(const T &item) 
    {...} 
    public T Pop() 
    {...} 
}; 

Questo è simile a prima vista, ma ci sono alcune importanti differenze. Innanzitutto, anziché una variante per ogni tipo fondamentale e una per tutti i tipi di oggetto, esiste una variante per ogni tipo viene creata un'istanza contro. Questo può essere un sacco di tipi!

La prossima importante differenza è (nella maggior parte dei compilatori C++) verrà compilata in ogni unità di traduzione in cui è utilizzata. Ciò può rallentare molto le compilazioni.

Un altro attributo interessante per i template di C++ è che possono essere applicati a cose diverse dalle classi - e quando lo sono, i loro argomenti possono essere rilevati automaticamente. Ad esempio:

template<typename T> 
T min(const T &a, const T &b) { 
    return a > b ? b : a; 
} 

Il tipo T verrà determinato automaticamente dal contesto in cui è utilizzata la funzione.

Questi attributi possono essere utilizzati per fini buoni, a scapito della vostra sanità mentale. Poiché un modello C++ viene ricompilato per ogni tipo utilizzato, e l'implementazione di un modello è sempre disponibile per il compilatore, C++ può eseguire inline molto aggressivi sui modelli. Aggiungete a ciò il rilevamento automatico dei valori dei template nelle funzioni, e potete creare anonymous pseudo-functions in C++, usando boost::lambda. Pertanto, un'espressione come:

_1 _2 + + _3

produce un oggetto con un serio paura tipo , che ha un operatore() che somma i suoi argomenti.

Ci sono molti altri angoli bui del sistema di template C++ - è uno strumento estremamente potente, ma può essere doloroso da pensare, e talvolta difficile da usare - in particolare quando ti dà un messaggio di errore di venti pagine. Il sistema C# è molto più semplice, meno potente, ma più facile da capire e più difficile da abusare.

+0

* Un altro attributo interessante ai modelli C++ s 'è che può da applicare ad altre cose oltre classi * - è questa la stessa cosa come C# ci permette di definire generici in funzioni (ad esempio 'T somefunc (ingresso T) {...}')? – dotNET

3

http://blogs.msdn.com/csharpfaq/archive/2004/03/12/88913.aspx

Approssimativamente, gran parte della differenza ha a che fare con il fatto che i modelli sono risolti al momento della compilazione, e generici sono risolti in fase di esecuzione.

+2

In realtà anche se i generici possono essere istanziati in fase di runtime (attraverso la riflessione, proprio come qualsiasi altra cosa), molto è capito al momento della compilazione. Ad esempio, il JIT produce un'implementazione specifica di 'List ' piuttosto che usare una versione comune cancellata dal tipo equivalente a 'Lista ' (questo è un modo in cui differisce da Java). –

+0

@Earwicker: parlamene. Ecco perché non è possibile fare una promozione generica (ad esempio concatenare un elenco a un elenco ). La funzionalità esiste nella CLI, ma hanno scelto di non implementarla in quel modo in C# (un errore, IMO). –

1

Questo blog entry from Eric Gunnerson copre questo argomento abbastanza bene.

La più grande differenza immediata è che i modelli sono una funzione di compilazione mentre i generici sono una funzione di runtime.