Cambia caso su tipo c #

Possibile duplicato:
C # – C’è un’alternativa migliore di questa per ‘triggersre il tipo’?

Ciao, suppongo di ottenere un grande if / else sul tipo di class. c’è un modo per farlo con un interruttore?

Esempio :

function test(object obj) { if(obj is WebControl) { }else if(obj is TextBox) { } else if(obj is ComboBox) { } 

eccetera …

Mi piacerebbe creare qualcosa di simile

 switch(obj) { case is TextBox: break; case is ComboBox: break; } 

}

No.

http://blogs.msdn.com/b/peterhal/archive/2005/07/05/435760.aspx

Riceviamo molte richieste di aggiunte al linguaggio C # e oggi parlerò di una delle più comuni – triggers il tipo. Il tipo di triggerszione sembra una funzionalità piuttosto utile e diretta: aggiungi un costrutto simile a un interruttore che triggers il tipo dell’espressione, piuttosto che il valore. Questo potrebbe sembrare qualcosa del genere:

 switch typeof(e) { case int: ... break; case string: ... break; case double: ... break; default: ... break; } 

Questo tipo di affermazione sarebbe estremamente utile per aggiungere metodi virtuali come l’invio su una gerarchia di tipi disgiunti o su una gerarchia di tipi contenenti tipi che non si possiedono. Vedendo un esempio come questo, si potrebbe facilmente concludere che la funzionalità sarebbe semplice e utile. Potrebbe anche farti pensare “Perché quei progettisti di linguaggio C # # e% $ pigri mi rendono la vita più semplice e aggiungo questa caratteristica linguistica semplice e rapida?”

Sfortunatamente, come molte caratteristiche linguistiche “semplici”, l’interruttore di tipo non è così semplice come appare per la prima volta. I problemi iniziano quando si guarda un esempio più significativo e non meno importante come questo:

 class C {} interface I {} class D : C, I {} switch typeof(e) { case C: … break; case I: … break; default: … break; } 

Link: https://blogs.msdn.microsoft.com/peterhal/2005/07/05/many-questions-switch-on-type/

Il codice seguente funziona più o meno come ci si aspetterebbe da un interruttore di tipo che guarda solo il tipo effettivo (ad es. Cosa viene restituito da GetType() ).

 public static void TestTypeSwitch() { var ts = new TypeSwitch() .Case((int x) => Console.WriteLine("int")) .Case((bool x) => Console.WriteLine("bool")) .Case((string x) => Console.WriteLine("string")); ts.Switch(42); ts.Switch(false); ts.Switch("hello"); } 

Ecco la macchina necessaria per farlo funzionare.

 public class TypeSwitch { Dictionary> matches = new Dictionary>(); public TypeSwitch Case(Action action) { matches.Add(typeof(T), (x) => action((T)x)); return this; } public void Switch(object x) { matches[x.GetType()](x); } } 

Sì, puoi inserire il nome …

 switch (obj.GetType().Name) { case "TextBox":... } 

Ecco un’opzione che rimane vera potrei farla al requisito dell’OP di essere in grado di accendere il tipo. Se strizzi abbastanza forte, sembra quasi una vera e propria affermazione.

Il codice chiamante assomiglia a questo:

 var @switch = this.Switch(new [] { this.Case(x => { /* WebControl code here */ }), this.Case(x => { /* TextBox code here */ }), this.Case(x => { /* ComboBox code here */ }), }); @switch(obj); 

La x in ogni lambda sopra è fortemente tipizzata. Nessuna fusione richiesta

E per far funzionare questa magia hai bisogno di questi due metodi:

 private Action Switch(params Func[] tests) { return o => { var @case = tests .Select(f => f(o)) .FirstOrDefault(a => a != null); if (@case != null) { @case(); } }; } private Func Case(Action action) { return o => o is T ? (Action)(() => action((T)o)) : (Action)null; } 

Quasi ti fa venire le lacrime agli occhi, giusto?

Tuttavia, funziona. Godere.

La cosa più semplice da fare potrebbe essere quella di utilizzare la dynamic, ovvero definire i metodi semplici come nella risposta di Yuval Peled:

 void Test(WebControl c) { ... } void Test(ComboBox c) { ... } 

Quindi non è ansible chiamare direttamente Test (obj), perché la risoluzione di sovraccarico viene eseguita in fase di compilazione. Devi assegnare il tuo object a una dynamic e quindi chiamare il metodo di prova:

 dynamic dynObj = obj; Test(dynObj);