2009-07-30 9 views
8

Duplicar posibles:
What are the differences between Generics in C# and Java… and Templates in C++?C# genéricos en comparación con las plantillas de C++

¿Cuáles son las diferencias entre C# genéricos en comparación con las plantillas de C++? Entiendo que no resuelven exactamente el mismo problema, entonces, ¿cuáles son los pros y los contras de ambos?

+4

Qué casualidad, ese es el tema de mi blog para hoy. http://blogs.msdn.com/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx –

+1

esto tiene * got * para ser exactamente duplicado. @Eric Lippert: Ooh, interesante, le dará una lectura – jalf

Respuesta

16

Usted puede considerar las plantillas de C++ para ser un lenguaje de programación interpretado funcional disfrazado de un sistema de genéricos. Si esto no te asusta, debería :)

C# genéricos son muy restringidos; puede parametrizar una clase en un tipo o tipos, y usar esos tipos en métodos. Así que, para tomar un ejemplo de MSDN, se podría hacer:

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

Y ahora se puede declarar un Stack<int> o Stack<SomeObject> y va a almacenar objetos de ese tipo, de forma segura (es decir, no se preocupa de poner en SomeOtherObject por Error).

Internamente, .NET runtime se especializará en variantes para tipos fundamentales como int, y una variante para tipos de objetos. Esto permite que la representación para Stack<byte> sea mucho más pequeña que la de Stack<SomeObject>, por ejemplo.

plantillas de C++ permiten un uso similar:

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

Esto es similar a primera vista, pero hay algunas diferencias importantes. En primer lugar, en lugar de una variante para cada tipo fundamental y para todos los tipos de objeto, existe una variante para , cada tipo se instancia contra. ¡Eso puede ser de muchos tipos!

La siguiente gran diferencia es que (en la mayoría de los compiladores de C++) se compilará en cada unidad de traducción en la que se utilice. Eso puede ralentizar la compilación.

Otro atributo interesante de las plantillas de C++ es que pueden aplicarse a otras cosas que no sean clases, y cuando lo son, sus argumentos se pueden detectar automáticamente. Por ejemplo:

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

El tipo T se determinará automáticamente por el contexto en el que se utiliza la función.

Estos atributos se pueden usar para fines buenos, a expensas de su cordura. Debido a que se recompila una plantilla de C++ para cada tipo que se usa en contra, y la implementación de una plantilla siempre está disponible para el compilador, C++ puede hacer una alineación muy agresiva en las plantillas. Agregue a eso la detección automática de valores de plantilla en funciones, y puede hacer anonymous pseudo-functions en C++, usando boost::lambda. Por lo tanto, una expresión como:

_1 + + _2 _3

Produce un objeto con un serio miedo tipo , que tiene un operador(), que se suma a sus argumentos.

Hay muchas otras esquinas oscuras del sistema de plantillas C++: es una herramienta extremadamente poderosa, pero puede ser doloroso pensarlo, y a veces difícil de usar, particularmente cuando le da un mensaje de error de veinte páginas de largo. El sistema C# es mucho más simple: menos potente, pero más fácil de entender y más difícil de abusar.

+0

* Otro atributo interesante para las plantillas de C++ es que pueden aplicarse a otras cosas que no sean clases * - ¿es esto lo mismo que C# nos permite definir genéricos en funciones (por ej. 'T SomeFunc (T input) {...}')? – dotNET

3

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

Aproximadamente, gran parte de la diferencia tiene que ver con el hecho de que las plantillas se resuelven en tiempo de compilación, y los genéricos se resuelven en tiempo de ejecución.

+2

En realidad, aunque los genéricos se pueden instanciar en tiempo de ejecución (a través de la reflexión, como cualquier otra cosa), mucho se resuelve en tiempo de compilación. Por ejemplo, el JIT produce una implementación específica de 'List ' en lugar de usar una versión borrada por tipos común equivalente a 'List ' (esta es una forma en que difiere de Java). –

+0

@Earwicker: cuéntame sobre eso. Es por eso que no puede hacer una promoción genérica (es decir, concatenar una lista en una lista ). La funcionalidad existe en la CLI, pero optaron por no implementarla de esa manera en C# (un error, IMO). –

1

Este blog entry from Eric Gunnerson trata este tema bastante bien.

La mayor diferencia inmediata es que las plantillas son una función de tiempo de compilación, mientras que los genéricos son una característica de tiempo de ejecución.