Existe-t-il un équivalent typedef en C #, ou d'une manière ou d'une autre pour obtenir une sorte de comportement similaire? J'ai fait quelques recherches sur Google, mais partout où je regarde, cela semble négatif. Actuellement, j'ai une situation similaire à la suivante:
class GenericClass<T>
{
public event EventHandler<EventData> MyEvent;
public class EventData : EventArgs { /* snip */ }
// ... snip
}
Maintenant, il ne faut pas un spécialiste des fusées pour comprendre que cela peut très rapidement conduire à beaucoup de dactylographie (excuses pour le jeu de mots horrible) lors de la tentative d'implémenter un gestionnaire pour cet événement. Cela finirait par ressembler à ceci:
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();
}
Sauf que dans mon cas, j'utilisais déjà un type complexe, pas seulement un int. Ce serait bien s'il était possible de simplifier un peu cela ...
Modifier: ie. peut-être en tapant le EventHandler au lieu de devoir le redéfinir pour obtenir un comportement similaire.
using MyClassDictionary = System.Collections.Generic.Dictionary<System.String, MyNamespace.MyClass>;
est-ce correct? Sinon, il ne semble pas tenir compte desusing
définitions ci-dessus.typedef uint8 myuuid[16];
via la directive "using".using myuuid = Byte[16];
ne compile pas.using
peut être utilisé uniquement pour créer des alias de type .typedef
semble être beaucoup plus flexible, car il peut créer un alias pour une déclaration entière (y compris les tailles de tableau). Y a-t-il une alternative dans ce cas?Jon a vraiment donné une bonne solution, je ne savais pas que tu pouvais faire ça!
Parfois, j'ai eu recours à l'héritage de la classe et à la création de ses constructeurs. Par exemple
Ce n'est pas la meilleure solution (sauf si votre assemblage est utilisé par d'autres personnes), mais cela fonctionne.
la source
public class FooList : LikeType<IReadOnlyList<Foo>> { ... }
, puis l' utiliser partout où vous attendez unIReadOnlyList<Foo>
. Ma réponse ci-dessous montre plus de détails.Foo
s'il est transmis par exemple à une méthode de modèle qui accepteList<T>
. Avec un typedef correct, ce serait possible.Si vous savez ce que vous faites, vous pouvez définir une classe avec des opérateurs implicites pour convertir entre la classe d'alias et la classe réelle.
Je n'approuve pas vraiment cela et je n'ai jamais utilisé quelque chose comme ça, mais cela pourrait probablement fonctionner pour certaines circonstances spécifiques.
la source
C # prend en charge une certaine covariance héritée pour les délégués d'événements, donc une méthode comme celle-ci:
Peut être utilisé pour vous abonner à votre événement, aucun casting explicite requis
Vous pouvez même utiliser la syntaxe lambda et l'intellisense sera tout fait pour vous:
la source
Je pense qu'il n'y a pas de typedef. Vous ne pouvez définir qu'un type de délégué spécifique au lieu du générique dans GenericClass, c'est-à-dire
Cela le raccourcirait. Mais qu'en est-il de la suggestion suivante:
Utilisez Visual Studio. De cette façon, lorsque vous avez tapé
il fournit déjà la signature complète du gestionnaire d'événements d'Intellisense. Appuyez sur TAB et c'est là. Acceptez le nom du gestionnaire généré ou modifiez-le, puis appuyez à nouveau sur TAB pour générer automatiquement le stub du gestionnaire.
la source
C ++ et C # manquent tous deux de moyens simples pour créer un nouveau type qui est sémantiquement identique à un type existant. Je trouve ces 'typedefs' totalement essentiels pour une programmation sécurisée et c'est vraiment dommage que c # ne les ait pas intégrés. La différence entre
void f(string connectionID, string username)
tovoid f(ConID connectionID, UserName username)
est évidente ...(Vous pouvez réaliser quelque chose de similaire en C ++ avec boost dans BOOST_STRONG_TYPEDEF)
Il peut être tentant d'utiliser l'héritage mais cela a quelques limitations majeures:
La seule façon de réaliser une chose similaire en C # est de composer notre type dans une nouvelle classe:
Bien que cela fonctionne, il est très détaillé pour un typedef. De plus, nous avons un problème avec la sérialisation (ie vers Json) car nous voulons sérialiser la classe via sa propriété Composed.
Vous trouverez ci-dessous une classe d'assistance qui utilise le «modèle de modèle curieusement récurrent» pour simplifier les choses:
Avec Composer, la classe ci-dessus devient simplement:
Et en plus la
SomeTypeTypeDef
volonté sérialisera à Json de la même manière quiSomeType
fait.J'espère que cela t'aides !
la source
Vous pouvez utiliser une bibliothèque open source et un package NuGet appelé LikeType que j'ai créé qui vous donneront le
GenericClass<int>
comportement que vous recherchez.Le code ressemblerait à:
la source
LikeType
bibliothèque.LikeType
Le but principal de 'est d'aider à l' obsession primitive , et en tant que tel, il ne veut pas que vous puissiez passer le type encapsulé comme s'il s'agissait du type encapsuleur. Comme dans, si je faisAge : LikeType<int>
alors si ma fonction a besoin d'unAge
, je veux m'assurer que mes appelants passent unAge
, pas unint
.Voici le code pour cela, profitez-en!, Je l'ai repris du type dotNetReference, l'instruction "using" à l'intérieur de la ligne d'espace de noms 106 http://referencesource.microsoft.com/#mscorlib/microsoft/win32/win32native.cs
la source
Pour les classes non scellées, héritez-en simplement:
Mais pour les classes scellées, il est possible de simuler le comportement typedef avec une telle classe de base:
la source
La meilleure alternative à
typedef
celle que j'ai trouvée en C # estusing
. Par exemple, je peux contrôler la précision du flotteur via les drapeaux du compilateur avec ce code:Malheureusement, cela nécessite que vous le placiez en haut de chaque fichier où vous utilisez
real_t
. Il n'existe actuellement aucun moyen de déclarer un type d'espace de noms global en C #.la source