Domanda

  

Eventuali duplicati:
   C # - Esiste una migliore alternativa di questo per 'interruttore del tipo'?

Se si vuole switch su un tipo di oggetto, qual è il modo migliore per fare questo?

Codice frammento

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

So che questo non funziona in questo modo, ma mi chiedevo come si potrebbe risolvere questo problema. È una dichiarazione if/else appropriata in questo caso?

O si utilizza l'opzione e aggiungere .ToString() al tipo?

È stato utile?

Soluzione

Se I davvero ha dovuto switch sul tipo di oggetto, userei .ToString(). Tuttavia, vorrei evitare a tutti i costi: IDictionary<Type, int> farà molto meglio, visitatore potrebbe essere un eccessivo ma per il resto è ancora un perfettamente bene soluzione.

Altri suggerimenti

Questo non risolverà il problema direttamente, come si vuole accendere i propri tipi definiti dall'utente, ma per il bene degli altri che vogliono solo accendere il built-in tipi, è possibile utilizzare il TypeCode enumerazione:

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

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

Nel post sul blog MSDN molte domande: Interruttore sul tipo è il motivo per cui alcune informazioni sul .NET non fornisce accensione tipi.

Come al solito -. Workaround esiste sempre

Questa non è mia, ma purtroppo ho perso la fonte. Rende l'accensione tipi possibili, ma io personalmente penso che sia abbastanza imbarazzante (l'idea dizionario è meglio):

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

Utilizzo:

 new Switch(foo)
     .Case<Fizz>
         (action => { doingSomething = FirstMethodCall(); })
     .Case<Buzz>
         (action => { return false; })

mi basta usare un'istruzione if. In questo caso:

Type nodeType = node.GetType();
if (nodeType == typeof(CasusNodeDTO))
{
}
else ... 

L'altro modo per farlo è:

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

Il primo esempio è vero per i tipi esatte solo, quando quest'ultimo verifica la presenza di eredità troppo.

Sono di fronte con lo stesso problema e sono imbattuto in questo post. È questo ciò che si intende con l'approccio 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;
    }
}

Se è così, non posso dire che io sono un fan di conciliare i numeri nel dizionario con le istruzioni case.

Questo sarebbe l'ideale ma il riferimento dizionario uccide:

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

C'è un'altra implementazione ho trascurato?

Si può fare questo:

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

Anche se sarebbe più elegante, è forse non così efficace come alcune delle altre risposte qui.

Si può fare questo:

function void PrintType(Type t) {
 var t = true;
 new Dictionary<Type, Action>{
   {typeof(bool), () => Console.WriteLine("bool")},
   {typeof(int),  () => Console.WriteLine("int")}
 }[t.GetType()]();
}

E 'chiaro e la sua facile. E 'un po' più lento di cache il dizionario da qualche parte .. ma per un sacco di codice di questo non importa comunque ..

Un approccio è quello di aggiungere un metodo puro GetNodeType virtuale () per NodeDTO e sovrascrivere nelle discendenti in modo che ogni discendente ritorna tipo effettivo.

A seconda di cosa si sta facendo nella dichiarazione switch, la risposta corretta è il polimorfismo. Basta mettere una funzione virtuale nella / classe base interfaccia e sovrascrivere per ogni tipo di nodo.

Io in realtà preferisco l'approccio dato come la risposta qui: C'è un'alternativa migliore di questo a 'interruttore del tipo'?

V'è tuttavia un buon argomento di non attuare alcun tipo di confronto methids in un linguaggio orientato agli oggetti come C #. Si potrebbe in alternativa estendere e aggiungere altre funzionalità desiderata usare l'ereditarietà.

Questo punto è stato discusso nei commenti degli autori blog qui: http: // blog. msdn.com/b/jaredpar/archive/2008/05/16/switching-on-types.aspx#8553535

Ho trovato questo un punto estremamente interessante che ha cambiato il mio approccio in una situazione simile e spero solo che questa aiuta gli altri.

Cordiali saluti, Wayne

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top