2011-01-08 9 views
16

¿Hay algo similar a esta plantilla de C++?C# genérico con constante

template <int A> 
class B 
{ 
    int f() 
    { 
     return A; 
    } 
} 

Quiero hacer cada instancia de B < 1>, B < 2>, etc (por ejemplo tupla) un tipo diferente.

Respuesta

18

La respuesta corta es no.

No se ajusta a la forma en que funcionan los genéricos C#, como se aplica a las plantillas C++.

Los genéricos .net no son una función de idioma, son una característica de tiempo de ejecución. El tiempo de ejecución sabe cómo instanciar los genéricos del bytecode genérico especial que es bastante restringido en comparación con lo que las plantillas de C++ pueden describir.

Compare esto con las plantillas C++, que básicamente ejemplifican todo el AST de la clase utilizando tipos sustituidos. Sería posible agregar instanciación basada en AST al tiempo de ejecución, pero sin duda sería mucho más complejo que los genéricos actuales.

Sin características como las matrices de tipo valor (que solo existen en el código inseguro), la creación de instancias recursivas de plantillas o la especialización de plantillas con tales parámetros tampoco serían muy útiles.

+1

Bueno, en tiempo de ejecución (JIT) .Net hace la instanciación. La instanciación es esencialmente una duplicación con modificaciones. No me opondría tanto a AST como a MSIL. Representación diferente de conceptos similares. –

12

C# no admite parámetros genéricos sin tipo, como C++.

Los genéricos C# son mucho más simples y menos capaces que las plantillas C++. MSDN tiene una lista sucinta de Differences Between C++ Templates and C# Generics.

+1

Sin embargo, la información adicional puede ser ". codificado "en tipos (por definición de contrato o de otro modo), es simple de ver con un conjunto fijo de tipos discretos (por ejemplo,' Vn: V, donde Vn.Value = n para todo Vn'), pero también hay [números de iglesia] (http://community.bartdesmet.net/blogs/bart/archive/2009/08/17/mis-using-c-4-0-dynamic-type-free-lambda-calcul us-church-numerals-and-more.aspx) - no es que recomiendo * cualquiera de los dos enfoques * aquí :-) –

+1

No es una respuesta incorrecta, pero sería bueno si proporcionara un enlace a los genéricos de C# y/o hablara sobre declaración genérica/"instanciación" vs. instanciación de plantilla. –

+3

@pst: seguro; puedes codificar información en tipos. También puede evitar genéricos y escribir muchas clases no genéricas. En todo caso; Agregué un enlace al artículo de MSDN que enumeraba las principales diferencias entre las plantillas y los genéricos. –

5

Los genéricos de C# están especializados en tiempo de ejecución, mientras que las plantillas de C++ se procesan en tiempo de compilación para crear un tipo completamente nuevo. Dado esto, el tiempo de ejecución simplemente no tiene las características para procesar los parámetros que no son de tipo (no es solo un problema de C#).

8

Una solución a esta limitación es definir una clase que a su vez expone el valor literal le interesa Por ejemplo:

public interface ILiteralInteger 
{ 
    int Literal { get; } 
} 

public class LiteralInt10 : ILiteralInteger 
{ 
    public int Literal { get { return 10; } } 
} 

public class MyTemplateClass<L> where L: ILiteralInteger, new() 
{ 
    private static ILiteralInteger MaxRows = new L(); 

    public void SomeFunc() 
    { 
     // use the literal value as required 
     if(MaxRows.Literal) ... 
    } 
} 

Uso:

var myObject = new MyTemplateClass<LiteralInt10>();