¿Hay un equivalente typedef en C #, o de alguna manera para obtener algún tipo de comportamiento similar? He buscado en Google, pero en todas partes me parece negativo. Actualmente tengo una situación similar a la siguiente:
class GenericClass<T>
{
public event EventHandler<EventData> MyEvent;
public class EventData : EventArgs { /* snip */ }
// ... snip
}
Ahora, no hace falta ser un experto en cohetes para darse cuenta de que esto puede conducir rápidamente a una gran cantidad de tipeo (disculpas por el horrible juego de palabras) al intentar implementar un controlador para ese evento. Terminaría siendo algo como esto:
GenericClass<int> gcInt = new GenericClass<int>;
gcInt.MyEvent += new EventHandler<GenericClass<int>.EventData>(gcInt_MyEvent);
// ...
private void gcInt_MyEvent(object sender, GenericClass<int>.EventData e)
{
throw new NotImplementedException();
}
Excepto que, en mi caso, ya estaba usando un tipo complejo, no solo un int. Sería bueno si fuera posible simplificar esto un poco ...
Editar: es decir. quizás escriba el EventHandler en lugar de tener que redefinirlo para obtener un comportamiento similar.
using MyClassDictionary = System.Collections.Generic.Dictionary<System.String, MyNamespace.MyClass>;
¿Es correcto? De lo contrario, no parece considerar lasusing
definiciones anteriores.typedef uint8 myuuid[16];
través de la directiva "uso".using myuuid = Byte[16];
no compilausing
se puede usar solo para crear alias de tipo .typedef
parece ser mucho más flexible, ya que puede crear un alias para una declaración completa (incluidos los tamaños de matriz). ¿Hay alguna alternativa en este caso?Jon realmente dio una buena solución, ¡no sabía que podías hacer eso!
A veces recurrí a heredar de la clase y crear sus constructores. P.ej
No es la mejor solución (a menos que su ensamblaje sea utilizado por otras personas), pero funciona.
fuente
public class FooList : LikeType<IReadOnlyList<Foo>> { ... }
y luego usarlo en cualquier lugar donde espere aIReadOnlyList<Foo>
. Mi respuesta a continuación muestra más detalles.Foo
si se pasa, por ejemplo, al método de plantilla que aceptaList<T>
. Con el typedef apropiado sería posible.Si sabe lo que está haciendo, puede definir una clase con operadores implícitos para convertir entre la clase de alias y la clase real.
En realidad no estoy de acuerdo con esto y nunca he usado algo como esto, pero esto probablemente podría funcionar para algunas circunstancias específicas.
fuente
C # admite algunas covarianzas heredadas para delegados de eventos, por lo que un método como este:
Se puede usar para suscribirse a su evento, no se requiere un elenco explícito
Incluso puede usar la sintaxis lambda y todo el intellisense se hará por usted:
fuente
Creo que no hay typedef. Solo puede definir un tipo de delegado específico en lugar del genérico en GenericClass, es decir
Esto lo haría más corto. Pero qué pasa con la siguiente sugerencia:
Usa Visual Studio. De esta manera, cuando escribiste
ya proporciona la firma completa del controlador de eventos de Intellisense. Presione TAB y está ahí. Acepte el nombre del controlador generado o cámbielo, y luego presione TAB nuevamente para generar automáticamente el código auxiliar del controlador.
fuente
Tanto C ++ como C # carecen de formas fáciles de crear un nuevo tipo que sea semánticamente idéntico a un tipo existente. Encuentro que tales 'typedefs' son totalmente esenciales para la programación segura de tipos y es una verdadera lástima que C # no los tenga incorporados. La diferencia entre
void f(string connectionID, string username)
avoid f(ConID connectionID, UserName username)
es obvia ...(Puede lograr algo similar en C ++ con impulso en BOOST_STRONG_TYPEDEF)
Puede ser tentador usar la herencia, pero eso tiene algunas limitaciones importantes:
La única forma de lograr algo similar en C # es componiendo nuestro tipo en una nueva clase:
Si bien esto funcionará, es muy detallado solo para un typedef. Además, tenemos un problema con la serialización (es decir, a Json) ya que queremos serializar la clase a través de su propiedad Composed.
A continuación se muestra una clase auxiliar que utiliza el "Patrón de plantilla curiosamente recurrente" para simplificar esto:
Con Composer, la clase anterior se vuelve simplemente:
Y además
SomeTypeTypeDef
, serializará a Json de la misma manera que loSomeType
hace.Espero que esto ayude !
fuente
Puede usar una biblioteca de código abierto y un paquete NuGet llamado LikeType que creé que le dará el
GenericClass<int>
comportamiento que está buscando.El código se vería así:
fuente
LikeType
biblioteca.LikeType
El propósito principal es ayudar con la obsesión primitiva , y como tal, no quiere que puedas pasar el tipo envuelto como si fuera el tipo de envoltorio. Como en, si hagoAge : LikeType<int>
entonces si mi función necesita unAge
, quiero asegurarme de que mis llamadas pasen unAge
, no unint
.Aquí está el código para ello, ¡disfrútelo! Lo tomé de dotNetReference, escriba la instrucción "using" dentro de la línea de espacio de nombres 106 http://referencesource.microsoft.com/#mscorlib/microsoft/win32/win32native.cs
fuente
Para las clases no selladas, simplemente herede de ellas:
Pero para las clases selladas es posible simular el comportamiento typedef con dicha clase base:
fuente
La mejor alternativa a la
typedef
que he encontrado en C # esusing
. Por ejemplo, puedo controlar la precisión de flotación a través de los indicadores del compilador con este código:Desafortunadamente, requiere que coloque esto en la parte superior de cada archivo donde lo use
real_t
. Actualmente no hay forma de declarar un tipo de espacio de nombres global en C #.fuente