2010-07-15 26 views
14

Así que en C++, estoy acostumbrado a ser capaz de hacer:¿Cómo alias un tipo incorporado en C#?

typedef int PeerId; 

Esto me permite hacer un tipo más auto-documentado, pero, además, también me permite hacer PEERID representan un tipo diferente en cualquier momento sin cambiar todo el código. Incluso podría convertir a PeerId en una clase si quisiera. Este tipo de extensibilidad es lo que quiero tener en C#, sin embargo, tengo problemas para descubrir cómo crear un alias para 'int' en C#.

Creo que puedo usar la instrucción using, pero solo tiene alcance en el archivo actual, creo, por lo que no funcionará (El alias debe ser accesible entre varios archivos sin ser redefinido). Tampoco puedo derivar una clase de los tipos incorporados (pero normalmente esto es lo que haría con los tipos de ref alias, como List o Dictionary). No estoy seguro de lo que puedo hacer. ¿Algunas ideas?

+0

¿Por qué no puede derivar de los tipos incorporados? – arootbeer

+1

Solo tengo curiosidad? ¿Cuál sería una situación o una razón por la que alguien quisiera hacer esto? Lo siento si esto suena raro, solo ignoro por qué no querrías usar int. Parece que sería confuso para otro desarrollador leer su código. –

+0

De acuerdo, le interesó leer esto, pero debe ser una mala práctica –

Respuesta

6

Se podría (ab) usar las conversiones implícitas:

struct PeerId 
{ 
    private int peer; 

    public static implicit operator PeerId(int i) 
    { 
     return new PeerId {peer=i}; 
    } 

    public static implicit operator int(PeerId p) 
    { 
     return p.peer; 
    } 
} 

Esto toma el mismo espacio que un int, y se puede do:

PeerId p = 3; 
int i = p; 

Pero estoy de acuerdo que probablemente no lo necesite.

+0

Lo hago a veces por tipos de valor un poco más complejos, pero no haría esto solo por tener un nombre. – ChaosPandion

16

Es necesario utilizar el nombre de tipo completo de esta manera:

using DWORD = System.Int32; 
+12

Esta solución no maneja esta parte de su pregunta: 'Creo que puedo usar la instrucción using, pero solo tiene alcance en el archivo actual, creo, por lo que no funcionará (el alias debe ser accesible entre múltiples archivos sin ser redefinidos) ' –

11

Resumen

Aquí está la respuesta corta:

  • typedefs son en realidad una variable utilizada por los generadores de código de tiempo de compilación.
  • C# se está diseñando para evitar agregar construcciones de lenguaje de generación de código.

Por lo tanto, el concepto de typedefs no encaja bien con el lenguaje C#.

Respuesta larga

En C++, tiene más sentido: C++ comenzó como un precompilador que escupió el código C, que luego fue compilado. Este "generador de códigos" que comienza todavía tiene efectos en las características modernas de C++ (es decir, las plantillas son esencialmente un lenguaje completo de Turing para generar clases y funciones en tiempo de compilación). En este contexto, un typedef tiene sentido porque es una forma de obtener el "resultado" de una fábrica de tipo de compilación o "algoritmo" que "devuelve" un tipo.

En este extraño metalenguaje (que pocos fuera de Boost han dominado), un typedef es realmente una variable.

Lo que describes es menos complejo, pero aún estás tratando de usar typedef como variable. En este caso, se usa como una variable de entrada. Entonces, cuando otro código usa typedef, realmente no usa ese tipo directamente. Más bien, actúa como un generador de código en tiempo de compilación, construyendo clases y métodos basados ​​en variables de entrada typedef'ed. Incluso si ignora las plantillas de C++ y simplemente mira C typedefs, el efecto es el mismo.

C++ y generativo Programación

C++ fue diseñado para ser un lenguaje multi-paradign (OO y de procedimiento, pero no es funcional hasta que salieron Boost). Curiosamente, las plantillas han evolucionado en un paradign inesperado: la programación generativa. (La programación generativa existía antes de C++, pero C++ la hizo popular). Los programas generativos son en realidad metaprogramas que, cuando se compilan, generan las clases y los métodos necesarios, que a su vez se compilan en ejecutables.

C# y generativo Programación

Nuestras herramientas están evolucionando lentamente en la misma dirección. Por supuesto, la emisión de reflejo puede usarse para la programación generativa "manual", pero es bastante dolorosa. La forma en que los proveedores de LINQ usan los árboles de expresión es de naturaleza muy generativa. Las plantillas T4 se acercan mucho, pero aún se quedan cortas. El "compilador como servicio" que, con suerte, formará parte de C# vNext, parece ser el más prometedor de todos, si se pudiera combinar con algún tipo de variable de tipo (como un typedef).

Ésta pieza del rompecabezas es still missing: programas generativos necesitan algún tipo de mecanismo de activación automática (en C++, esto es manejado por implícita de instancias de plantilla).

Sin embargo, es explícitamente no una meta de C# para tener cualquier tipo de "generador de código" en el lenguaje C# como plantillas de C++ (probablemente por el bien de la comprensibilidad; muy pocos programadores de C++ entienden C plantillas ++). Este será probablemente un nicho satisfecho por T4 en lugar de C#.

Conclusión (repitiendo el Resumen)

Todo lo anterior es para decir esto:

  • typedefs son una variable utilizada por los generadores de código.
  • C# se está diseñando para evitar agregar construcciones de lenguaje de generación de código.

Por lo tanto, el concepto de typedefs no encaja bien con el lenguaje C#.

+3

Respuesta extremadamente informativa, sin embargo, no conlleva ninguna información que yo no supiera ni responde mi pregunta inicial. Simplemente mencioné typedefs para darles a todos un ejemplo de lo que estoy pensando/esperando. Los alias no necesariamente tienen que ser compilados y pueden tomar muchas formas, como la derivación. Si pudiera hacer esto: "public class PeerId: int {}", eso sería suficiente y resolvería mi problema perfectamente. –

+0

También +1 la respuesta para obtener información interesante y útil –

1

Redefinir tipos fundamentales solo por cambiar el nombre es pensar C++ y no concuerda con el C# más puro orientado a objetos. Cada vez que tenga la necesidad de calzar un concepto de un idioma a otro, debe detenerse y pensar si tiene sentido o no y tratar de mantenerse nativo de la plataforma.

El requisito de poder cambiar fácilmente el tipo subyacente se puede satisfacer definiendo su propio tipo de valor. Junto con operadores de conversión implícitos y operadores aritméticos, tiene la capacidad de definir tipos muy potentes. Si le preocupa el rendimiento para agregar capas sobre tipos simples, no lo haga. 99% de posibilidades de que no lo haga, y el 1% de posibilidades es que, en caso de que lo haga, no sea el "fruto más fácil" de la optimización del rendimiento.

3

A veces también siento que necesito tipos (enteros) para propósitos similares al OP.

Si no te importa los elencos de ser explícita (que en realidad quiero que sean) se puede hacer esto:

enum PeerId : int {};

también trabajar para byte, sbyte, short, ushort, uint, long, o ulong (obviamente). No es exactamente el uso previsto de enum, pero funciona.

Cuestiones relacionadas