Question

  

Possible en double:    C # - Y at-il une meilleure autre que cela pour 'interrupteur du type'?

Si vous voulez switch sur un type d'objet, ce qui est la meilleure façon de le faire?

Extrait de code

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 vous pourriez résoudre ce problème. Est-ce une déclaration if/else appropriée dans ce cas?

Ou utilisez-vous le commutateur et ajouter .ToString() au type?

Était-ce utile?

La solution

Si I vraiment devaient switch sur le type d'objet, j'utiliser .ToString(). Cependant, je l'éviter à tout prix: IDictionary<Type, int> fera beaucoup mieux, visiteur peut-être un surpuissant mais sinon il est encore une solution parfaitement bien.

Autres conseils

Cela ne résoudra pas directement votre problème que vous voulez changer vos propres types définis par l'utilisateur, mais au profit d'autres qui ne veulent allumer types intégrés, vous pouvez utiliser le l'énumération TypeCode:

switch (Type.GetTypeCode(node.GetType()))
{
    case TypeCode.Decimal:
        // Handle Decimal
        break;

    case TypeCode.Int32:
        // Handle Int32
        break;
     ...
}

Dans le blog MSDN De nombreuses questions: commutateur le type des informations sur les raisons .NET ne fournit pas la mise sous tension types.

Comme d'habitude -. Solutions de contournement existe toujours

Celui-ci est pas à moi, mais malheureusement j'ai perdu la source. Il fait passer sur les types possibles, mais je pense personnellement qu'il est assez maladroit (l'idée dictionnaire est mieux):

  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; })

Je venais d'utiliser 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 que, lorsque ce dernier vérifie l'héritage aussi.

Je suis confronté au même problème et suis tombé sur ce poste. Est-ce ce qui signifie 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 oui, je ne peux pas dire que je suis fan de réconcilier les chiffres dans le dictionnaire avec les déclarations de cas.

Ce serait idéal, mais la référence 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 at-il une autre application que j'ai négligé?

Vous pouvez faire ceci:

if (node is CasusNodeDTO)
{
    ...
}
else if (node is BucketNodeDTO)
{
    ...
}
...

Alors que ce serait plus élégant, il est peut-être pas aussi efficace que certains des 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()]();
}

Il est clair et il est facile. Un peu plus lent que la mise en cache quelque part le dictionnaire .. mais pour beaucoup de code ce ne sera pas question de toute façon ..

Une approche consiste à ajouter une méthode GetNodeType virtuelle pure () pour NodeDTO et remplacer dans les descendants de sorte que chaque descendant renvoie type réel.

En fonction de ce que vous faites dans l'instruction switch, la bonne réponse est le polymorphisme. Il suffit de mettre une fonction virtuelle dans l'interface / classe de base et remplacer, pour chaque type de noeud.

je préfère l'approche la réponse donnée ici: Y at-il une meilleure alternative que cela 'interrupteur du type'?

Il y a cependant un bon argument de ne pas mettre en œuvre des methids de comparaison de type dans un langage orienté objet comme C #. Vous pouvez comme alternative étendre et d'ajouter des fonctionnalités supplémentaires requises en utilisant l'héritage.

Ce point a été discuté dans les commentaires du blog 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 espère seulement que cela aide les autres.

Cordialement, Wayne

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top