Utilisation de Case / Switch et GetType pour déterminer l'objet [dupliquer]
possible Duplicate:
C# - y a-t-il une meilleure alternative que celle de "switch on type"?
Si vous voulez switch
sur un type d'objet, quelle est la meilleure façon de le faire?
private int GetNodeType(NodeDTO node)
{
switch (node.GetType())
{
case typeof(CasusNodeDTO):
return 1;
case typeof(BucketNodeDTO):
return 3;
case typeof(BranchNodeDTO):
return 0;
case typeof(LeafNodeDTO):
return 2;
default:
return -1;
}
}
je sais que ça ne marche pas comme ça, mais je me demandais comment tu pouvais résoudre ça.
Est un if/else
déclaration appropriée dans ce cas?
ou utilisez-vous l'interrupteur et ajoutez .ToString()
au type?
11 réponses
Si je vraiment devait switch
sur le type d'objet, j'utiliserais .ToString()
. Cependant, je l'éviterais à tout prix: IDictionary<Type, int>
fera beaucoup mieux, visiteur peut-être un surmenage, mais autrement il est encore une solution parfaitement fine.
cela ne résoudra pas directement votre problème que vous voulez activer sur vos propres types définis par l'utilisateur, mais pour le bénéfice d'autres qui veulent seulement activer sur les types intégrés, vous pouvez utiliser le TypeCode enumeration:
switch (Type.GetTypeCode(node.GetType()))
{
case TypeCode.Decimal:
// Handle Decimal
break;
case TypeCode.Int32:
// Handle Int32
break;
...
}
Dans MSDN blog de Nombreuses Questions: sur le switch de type , quelques informations sur les raisons de .NET ne fournit pas de commutation sur les types.
comme d'habitude - workarounds existe toujours.
celui-ci n'est pas à moi, mais malheureusement j'ai perdu la source. Cela permet de changer de type, mais je pense personnellement que c'est assez embarrassant (l'idée du dictionnaire est meilleure):
public class Switch
{
public Switch(Object o)
{
Object = o;
}
public Object Object { get; private set; }
}
/// <summary>
/// Extensions, because otherwise casing fails on Switch==null
/// </summary>
public static class SwitchExtensions
{
public static Switch Case<T>(this Switch s, Action<T> a)
where T : class
{
return Case(s, o => true, a, false);
}
public static Switch Case<T>(this Switch s, Action<T> a,
bool fallThrough) where T : class
{
return Case(s, o => true, a, fallThrough);
}
public static Switch Case<T>(this Switch s,
Func<T, bool> c, Action<T> a) where T : class
{
return Case(s, c, a, false);
}
public static Switch Case<T>(this Switch s,
Func<T, bool> c, Action<T> a, bool fallThrough) where T : class
{
if (s == null)
{
return null;
}
T t = s.Object as T;
if (t != null)
{
if (c(t))
{
a(t);
return fallThrough ? s : null;
}
}
return s;
}
}
Utilisation:
new Switch(foo)
.Case<Fizz>
(action => { doingSomething = FirstMethodCall(); })
.Case<Buzz>
(action => { return false; })
j'utiliserais juste une instruction if. Dans ce cas:
Type nodeType = node.GetType();
if (nodeType == typeof(CasusNodeDTO))
{
}
else ...
L'autre façon de le faire est:
if (node is CasusNodeDTO)
{
}
else ...
le premier exemple est vrai pour les types exacts seulement, où le dernier contrôle pour l'héritage aussi.
je suis confronté au même problème et suis tombé sur ce post. Est-ce que c'est ce qu'on entend par l'approche iDictionnaire:
Dictionary<Type, int> typeDict = new Dictionary<Type, int>
{
{typeof(int),0},
{typeof(string),1},
{typeof(MyClass),2}
};
void Foo(object o)
{
switch (typeDict[o.GetType()])
{
case 0:
Print("I'm a number.");
break;
case 1:
Print("I'm a text.");
break;
case 2:
Print("I'm classy.");
break;
default:
break;
}
}
si c'est le cas, je ne peux pas dire que je suis un fan de concilier les nombres dans le dictionnaire avec les déclarations de cas.
ce serait idéal mais la référence au dictionnaire le tue:
void FantasyFoo(object o)
{
switch (typeDict[o.GetType()])
{
case typeDict[typeof(int)]:
Print("I'm a number.");
break;
case typeDict[typeof(string)]:
Print("I'm a text.");
break;
case typeDict[typeof(MyClass)]:
Print("I'm classy.");
break;
default:
break;
}
}
y a-t-il une autre implémentation que j'ai oubliée?
Vous pouvez faire ceci:
if (node is CasusNodeDTO)
{
...
}
else if (node is BucketNodeDTO)
{
...
}
...
Tandis que, plus élégante, c'est peut-être pas aussi efficace que d'autres réponses ici.
Vous pouvez faire ceci:
function void PrintType(Type t) {
var t = true;
new Dictionary<Type, Action>{
{typeof(bool), () => Console.WriteLine("bool")},
{typeof(int), () => Console.WriteLine("int")}
}[t.GetType()]();
}
c'est clair et facile. C'est un peu plus lent que de cacher le dictionnaire quelque part.. mais pour beaucoup de code cela n'a pas d'importance de toute façon..
une approche consiste à ajouter une méthode pure virtual GetNodeType() pour NodeDTO et la surcharger dans les descendants de sorte que chaque descendant retourne le type réel.
selon ce que vous faites dans la déclaration switch, la bonne réponse est polymorphisme. Il suffit de mettre une fonction virtuelle dans la classe interface/base et de surcharger pour chaque type de noeud.
j'utiliserais la chaîne (nom) en haut de l'interrupteur:
private int GetNodeType(NodeDTO node)
{
switch (node.GetType().Name)
{
case "CasusNodeDTO":
return 1;
break;
case "BucketNodeDTO":
return 3;
break;
// ...
default:
return -1;
break;
}
}
je préfère en fait l'approche donnée comme la réponse ici: Est-il une meilleure alternative que de ce "de type"?
il y a cependant un bon argument sur le fait de ne pas mettre en œuvre n'importe quel type de methids de comparaison dans un langage orienté objet comme C#. Vous pouvez comme alternative étendre et ajouter des fonctionnalités supplémentaires requises en utilisant l'héritage.
ce point a été discuté dans les commentaires des auteurs blog ici: http://blogs.msdn.com/b/jaredpar/archive/2008/05/16/switching-on-types.aspx#8553535
j'ai trouvé ce point extrêmement intéressant qui a changé mon approche dans une situation similaire et j'espère seulement que cela aide les autres.
Salutations, Wayne