Génériques C # et vérification de type

J’ai une méthode qui utilise un IList tant que paramètre. Je dois vérifier quel est le type de cet object et faire quelque chose en fonction de cela. J’essayais d’utiliser la valeur T , mais le compilateur ne le permet pas. Ma solution est la suivante:

 private static ssortingng BuildClause(IList clause) { if (clause.Count > 0) { if (clause[0] is int || clause[0] is decimal) { //do something } else if (clause[0] is Ssortingng) { //do something else } else if (...) //etc for all the types else { throw new ApplicationException("Invalid type"); } } } 

Il doit y avoir une meilleure façon de le faire. Est-il possible de vérifier le type de T transmis et d’utiliser une instruction switch ?

Vous pouvez utiliser des surcharges:

 public static ssortingng BuildClause(List l){...} public static ssortingng BuildClause(List l){...} public static ssortingng BuildClause(List l){...} 

Ou vous pouvez inspecter le type du paramètre générique:

 Type listType = typeof(T); if(listType == typeof(int)){...} 

Vous pouvez utiliser typeof(T) .

 private static ssortingng BuildClause(IList clause) { Type itemType = typeof(T); if(itemType == typeof(int) || itemType == typeof(decimal)) ... } 

Par défaut, sachez qu’il n’y a pas de grande façon. Auparavant, cela m’a frustré et a écrit une petite classe utilitaire qui a aidé un peu et a rendu la syntaxe un peu plus propre. Essentiellement, il transforme le code en

 TypeSwitcher.Do(clause[0], TypeSwitch.Case(x => ...), // x is an int TypeSwitch.Case(d => ...), // d is a decimal TypeSwitch.Case(s => ...)); // s is a ssortingng 

Le blogue complet et les détails sur la mise en œuvre sont disponibles ici

Le type d’opérateur …

 typeof(T) 

… ne fonctionnera pas avec l’instruction c # switch. Mais qu’en est-il de ça? Le post suivant contient une classe statique …

Existe-t-il une meilleure alternative à «activer le type»?

… cela vous permettra d’écrire du code comme celui-ci:

 TypeSwitch.Do( sender, TypeSwitch.Case 

Votre construction va complètement à l’encontre du but d’une méthode générique. C’est moche express parce qu’il doit y avoir une meilleure façon de réaliser ce que vous essayez d’accomplir, même si vous ne nous avez pas donné assez d’informations pour savoir ce que c’est.

Pour tous ceux qui disent que vérifier les types et faire quelque chose en fonction du type n’est pas une bonne idée pour les génériques, je suis en quelque sorte d’accord, mais je pense qu’il pourrait y avoir certaines circonstances dans lesquelles cela est parfaitement logique.

Par exemple, si vous avez une classe qui est implémentée comme ça (Remarque: je ne montre pas tout ce que ce code fait pour simplifier et simplement copier-coller afin qu’il ne puisse pas être conçu comme le code complet cela fait passer le message. En outre, Unit est un enum):

 public class FoodCount : BaseFoodCount { public TValue Value { get; set; } public override ssortingng ToSsortingng() { if (Value is decimal) { // Code not cleaned up yet // Some code and values defined in base class mstrValue = Value.ToSsortingng(); decimal mdecValue; decimal.TryParse(mstrValue, out mdecValue); mstrValue = decimal.Round(mdecValue).ToSsortingng(); mstrValue = mstrValue + mstrUnitOfMeasurement; return mstrValue; } else { // Simply return a ssortingng ssortingng str = Value.ToSsortingng() + mstrUnitOfMeasurement; return str; } } } 

 public class SaturatedFat : FoodCountWithDailyValue { public SaturatedFat() { mUnit = Unit.g; } } public class Fiber : FoodCount { public Fiber() { mUnit = Unit.g; } } public void DoSomething() { nusortingtionFields.SaturatedFat oSatFat = new nusortingtionFields.SaturatedFat(); ssortingng mstrValueToDisplayPreFormatted= oSatFat.ToSsortingng(); } 

Donc, en résumé, je pense qu’il y a des raisons valables pour lesquelles vous pourriez vouloir vérifier quel type est le générique, afin de faire quelque chose de spécial.

Il n’y a aucun moyen d’utiliser l’instruction switch pour ce que vous voulez faire. L’instruction switch doit être fournie avec des types intégraux, qui n’incluent pas les types complexes tels qu’un object “Type” ou tout autre type d’object.

Vous pouvez faire typeOf(T) , mais je voudrais vérifier votre méthode et vous assurer de ne pas violer la responsabilité unique ici. Ce serait une odeur de code, et cela ne veut pas dire que cela ne devrait pas être fait mais que vous devriez être prudent.

Le but des génériques est de pouvoir construire des algorthims agnostiques si vous ne vous souciez pas du type ou du moment où cela correspond à un certain ensemble de critères. Votre implémentation n’est pas très générique.

Que dis-tu de ça :

  // Checks to see if the value passed is valid. if (!TypeDescriptor.GetConverter(typeof(T)).IsValid(value)) { throw new ArgumentException(); }