Duplicate possible:
C # - Existe-t-il une meilleure alternative que celle-ci au "type de commutation"?
Si vous voulez switch
sur un type d'objet, quel est le meilleur moyen 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 cela ne fonctionne pas de cette façon, mais je me demandais comment résoudre ce problème. Une déclaration if/else
est-elle appropriée dans ce cas?
Ou utilisez-vous le commutateur et ajoutez-vous .ToString()
au type?
Si je vraiment devais switch
sur le type d'objet, j'utiliserais .ToString()
. Cependant, je l'éviterais à tout prix: IDictionary<Type, int>
ferait beaucoup mieux, visiteur peut-être un excès, mais sinon, c'est toujours une solution parfaite.
Cela ne résoudra pas directement votre problème car vous souhaitez activer vos propres types définis par l'utilisateur, mais pour le bénéfice des autres utilisateurs souhaitant uniquement activer les types intégrés, vous pouvez utiliser le type TypeCode énumération:
switch (Type.GetTypeCode(node.GetType()))
{
case TypeCode.Decimal:
// Handle Decimal
break;
case TypeCode.Int32:
// Handle Int32
break;
...
}
Dans le blog MSDN Nombreuses questions: activez le type contient des informations sur les raisons pour lesquelles . NET ne fournit pas de types de commutation.
Comme d'habitude - les solutions de contournement existent toujours.
Celui-ci ne m'appartient pas, mais malheureusement, j'ai perdu la source. Cela permet de changer de type, mais je trouve personnellement que c'est assez bizarre (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;
}
}
Usage:
new Switch(foo)
.Case<Fizz>
(action => { doingSomething = FirstMethodCall(); })
.Case<Buzz>
(action => { return false; })
Je voudrais juste utiliser une déclaration si. Dans ce cas:
Type nodeType = node.GetType();
if (nodeType == typeof(CasusNodeDTO))
{
}
else ...
L'autre façon de faire est:
if (node is CasusNodeDTO)
{
}
else ...
Le premier exemple est vrai pour les types exacts uniquement, où ce dernier vérifie également l'héritage.
Je suis confronté au même problème et suis tombé sur ce post. Est-ce que c'est ce que l'on entend par l'approche IDictionary:
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 partisan de la réconciliation des chiffres du dictionnaire avec les instructions de cas.
Ce serait l'idéal mais la référence du 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;
}
}
Existe-t-il une autre implémentation que j'ai oubliée?
Tu peux le faire:
if (node is CasusNodeDTO)
{
...
}
else if (node is BucketNodeDTO)
{
...
}
...
Bien que cela soit plus élégant, ce n’est peut-être pas aussi efficace que certaines des autres réponses données ici.
Tu peux le faire:
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 c'est facile. C'est un peu plus lent que de mettre le dictionnaire en cache quelque part .. mais pour beaucoup de code cela n'aura pas d'importance de toute façon ..
Une approche consiste à ajouter une méthode virtuelle GetNodeType () pure à NodeDTO et à la remplacer dans les descendants afin que chaque descendant renvoie le type réel.
Selon ce que vous faites dans l'instruction switch, la bonne réponse est le polymorphisme. Il suffit de mettre une fonction virtuelle dans la classe d’interface/base et de la remplacer pour chaque type de nœud.
Je pense que c'est mieux:
private int GetNodeType(NodeDTO node)
{
switch (node.GetType().Name)
{
case nameof(CasusNodeDTO):
return 1;
break;
case nameOf(BucketNodeDTO):
return 3;
break;
// ...
default:
return -1;
break;
}
}
En fait, je préfère l’approche donnée comme réponse ici: Existe-t-il une meilleure alternative que celle-ci pour "activer le type"?
Cependant, il existe un bon argument pour ne pas implémenter de méthode de comparaison de type dans un langage orienté objet comme C #. Vous pouvez également étendre et ajouter des fonctionnalités supplémentaires requises à l'aide de l'héritage.
Ce point a été abordé dans les commentaires du blog des auteurs 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 aidera les autres.
Cordialement, Wayne