2009-07-30 14 views
8

Powiel możliwe:
What are the differences between Generics in C# and Java… and Templates in C++?C# rodzajowych w porównaniu do C++ szablony

Jakie są różnice między C# rodzajowych w porównaniu do szablonów C++? Rozumiem, że nie rozwiązują dokładnie tego samego problemu, więc jakie są plusy i minusy obu?

+4

Co za zbieg okoliczności, to jest mój blog na dzisiaj. http://blogs.msdn.com/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx –

+1

to * ma * być dokładnym duplikatem. @Eric Lippert: Ooh, interesujące, da mu odczyt – jalf

Odpowiedz

16

Można rozważyć C++ szablony być interpretowane, funkcjonalny język programowania przebrany jako system generycznych. Jeśli to Cię nie przestraszy, powinno być :)

C# leki generyczne są bardzo ograniczone; możesz sparametryzować klasę na typie lub typach i użyć tych typów w metodach. Tak więc, aby wziąć przykład z MSDN, można zrobić:

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

I teraz można zadeklarować Stack<int> lub Stack<SomeObject> i będzie ona przechowywać obiekty tego typu, bezpiecznie (czyli nie martwi się o umieszczenie w SomeOtherObject przez błąd).

Wewnętrznie środowisko wykonawcze .NET specjalizuje się w wariantach dla typów podstawowych, takich jak int i wariant dla typów obiektów. Dzięki temu reprezentacja dla Stack<byte> jest znacznie mniejsza niż na przykład z Stack<SomeObject>.

Szablony C++ pozwalają podobne zastosowanie:

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

To wygląda podobnie na pierwszy rzut oka, ale istnieje kilka istotnych różnic. Po pierwsze, zamiast jednego wariantu dla każdego typu podstawowego i jednego dla wszystkich typów obiektów, istnieje jeden wariant dla dla każdego typu, który jest tworzony dla. To może być wiele rodzajów!

Następną ważną różnicą jest (w większości kompilatorów C++), że zostanie skompilowana w każdej jednostce tłumaczeniowej, w której jest używana. To może spowolnić kompilacje.

Innym interesującym atrybutem szablonów C++ jest to, że można je zastosować do rzeczy innych niż klasy - a gdy tak się stanie, ich argumenty mogą zostać automatycznie wykryte. Na przykład:

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

Typ T zostanie automatycznie określony przez kontekst, w którym funkcja jest używana.

Atrybuty te można wykorzystać do dobrych celów kosztem zdrowia psychicznego. Ponieważ szablon C++ jest rekompilowany dla każdego typu, z którego jest używany, a implementacja szablonu jest zawsze dostępna dla kompilatora, C++ może wykonywać bardzo agresywne inlining na szablonach. Dodaj do tego automatyczne wykrywanie wartości szablonów w funkcjach i możesz dokonać anonymous pseudo-functions w C++, używając boost::lambda. Zatem wyrażenie jak:

_1 + _2 + _3

Generuje obiekt z poważnie przerażające typu, który ma operatora(), które dodaje się do jego argumentów.

Istnieje wiele innych ciemnych zakątków systemu szablonów C++ - jest to niezwykle potężne narzędzie, ale może być bolesne, aby myśleć, a czasami trudne w użyciu - szczególnie, gdy daje dwadzieścia stronicowy komunikat o błędzie. System C# jest znacznie prostszy - mniej wydajny, ale łatwiejszy do zrozumienia i trudniejszy do nadużywania.

+0

* Innym interesującym atrybutem szablonów C++ jest to, że można je zastosować do rzeczy innych niż klasy * - czy to samo, co C#, pozwala nam definiować generyczne funkcje (np. 'T SomeFunc (wejście T) {...}')? – dotNET

3

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

grubsza, znacznie różnicy ma do czynienia z faktem, że szablony są rozwiązywane w czasie kompilacji i generyczne są rozwiązywane przy starcie.

+2

Właściwie chociaż generyczne mogą być tworzone w czasie wykonywania (poprzez odbicie, tak jak wszystko inne), wiele jest zorientowanych w czasie kompilacji. Na przykład JIT tworzy konkretną implementację 'List ' zamiast używania wspólnej, wymazanej wersji, równoważnej 'List ' (jest to jeden sposób, który różni się od Javy). –

+0

@Earwicker: opowiedz mi o tym. Dlatego nie można wykonywać ogólnej promocji (tj. Łączenie listy z listą ). Funkcjonalność istnieje w interfejsie CLI, ale zdecydowali się nie implementować go w ten sposób w języku C# (błąd, IMO). –

1

Ten blog entry from Eric Gunnerson obejmuje ten temat całkiem dobrze.

Największa bezpośrednia różnica polega na tym, że szablony są funkcją czasu kompilacji, podczas gdy generyczne są funkcjami uruchomieniowymi.