Prima di iniziare a criticare e avermi §8.7.2 di C# specification, leggere attentamente :)istruzione Switch con i non-espressione-costante - Estende la capacità C#/IDE
Sappiamo tutti quanto l'interruttore si presenta come in C#. Ok, quindi prendere in considerazione la classe MainWindow
con "nasty" Bar metodo
static int barCounter = 0;
public static int Bar()
{
return ++barCounter;
}
Da qualche parte in questa classe abbiamo codice come questo
Action switchCode =() =>
{
switch (Bar())
{
case 1:
Console.WriteLine("First");
break;
case 2:
Console.WriteLine("Second");
break;
}
};
switchCode();
switchCode();
Nella finestra della console vedremo
First
Second
Usando le espressioni in C# potremmo fare lo stesso - scrivere lo stesso codice
var switchValue = Expression.Call(typeof(MainWindow).GetMethod("Bar"));
var WriteLine = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) });
var @switch = Expression.Switch(switchValue,
Expression.SwitchCase(
Expression.Call(WriteLine, Expression.Constant("First")),
Expression.Constant(1)
),
Expression.SwitchCase(
Expression.Call(WriteLine, Expression.Constant("Second")),
Expression.Constant(2)
)
);
Action switchCode = Expression.Lambda<Action>(@switch).Compile();
switchCode();
switchCode();
In DebugView abbiamo potuto vedere "code-behind" questa espressione
.Switch (.Call WpfApplication1.MainWindow.Bar()) {
.Case (1):
.Call System.Console.WriteLine("First")
.Case (2):
.Call System.Console.WriteLine("Second")
}
EHMM, cosa succede se usiamo Expression.Call
invece Expression.Constant
?
public static bool foo1() { return false; }
public static bool foo2() { return true; }
// .....
var foo1 = Ex.Call(typeof(MainWindow).GetMethod("foo1"));
var foo2 = Ex.Call(typeof(MainWindow).GetMethod("foo2"));
var switchValue = Ex.Call(typeof(MainWindow).GetMethod("Bar"));
var WriteLine = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) });
var @switch = Ex.Switch(Ex.Constant(true),
Ex.SwitchCase(
Ex.Call(WriteLine, Ex.Constant("First")),
foo1
),
Ex.SwitchCase(
Ex.Call(WriteLine, Ex.Constant("OK!")),
Ex.Equal(switchValue, Ex.Constant(2))
),
Ex.SwitchCase(
Ex.Call(WriteLine, Ex.Constant("Second")),
foo2
)
);
Action switchCode = Ex.Lambda<Action>(@switch).Compile();
switchCode();
switchCode();
spettacoli finestra della console, come ci aspettavamo
Second
OK!
E DebugView
.Switch (True) {
.Case (.Call WpfApplication1.MainWindow.foo1()):
.Call System.Console.WriteLine("First")
.Case (.Call WpfApplication1.MainWindow.Bar() == 2):
.Call System.Console.WriteLine("OK!")
.Case (.Call WpfApplication1.MainWindow.foo2()):
.Call System.Console.WriteLine("Second")
}
Quindi è possibile utilizzare l'espressione non costante nel caso-statement :)
Ok, ho capito che questo è un piccolo codice "disordinato". Ma ecco che arriva la mia domanda (finalmente: P):
Esiste un modo per estendere la funzionalità di IDE/VisualStudio/compilatore per farlo, ma con un codice più elegante?
Qualcosa di simile
switch (true)
{
case foo1():
Console.WriteLine("First");
break;
case Bar() == 2:
Console.WriteLine("OK!");
break;
case foo2():
Console.WriteLine("Second");
break;
}
So che questo sarà un po 'di estensione e il codice non sarà lo stesso (non la stessa prestazione). Ma mi chiedo se sia addirittura possibile "cambiare" il codice al volo - come la funzione anonima o il rendimento restituito è trasformato in classe annidata.
Spero che qualcuno riesca a leggere il testo sopra e lasciare qualche indizio.
Sembra un sacco di sforzi per risolvere un problema che non esiste. Gli switch possono offrire un tempo di ricerca costante. Questa è una grande cosa in scenari in cui hai un gran numero di valori possibili. Basta usare una serie di 'if/else if' e passare alla risoluzione di problemi reali (o usare un linguaggio che favorisca l'espressività oltre le prestazioni su tutta la linea). –
@ Eds. Pensi di non sapere di
if/else if
? Questo è più "una sfida" su come fare questo, non un problema "come posso usare una serie di dichiarazioni di condizione booleana". In effetti ho usato PHP e JavaScript, c'è qualcosa come sopra molto. Se vuoi qualche problema reale: http://stackoverflow.com/q/9536087/1245315 – CarnifexNo, penso che stai sprecando il tuo tempo e non utilizzandolo per risolvere problemi reali. Sì, ci sono linguaggi che possono fare ciò che tu proponi, ma non possono nemmeno offrire una ricerca a tempo costante. Hai solo una quantità limitata di tempo in questa vita, il mio consiglio è di non sprecarlo in cose come questa che non hanno alcun beneficio apprezzabile per nessuno. Un linguaggio di programmazione è solo uno strumento, non un obiettivo a sé stante. Per quanto riguarda la tua altra domanda ... no grazie, le stranezze dell'interfaccia utente non mi interessano, ed è per questo che non costruisco l'interfaccia utente per vivere :) –