還沒有一個完整的比喻在C#的switch
和SwitchExpression
之間。在另一個方向上,認爲你可以有:
var value = Expression.Parameter(typeof(int));
var meth = Expression.Lambda<Func<int, string>>(
Expression.Switch(
value,
Expression.Call(value, typeof(object).GetMethod("ToString")),
Expression.SwitchCase(Expression.Constant("Zero"), Expression.Constant(0, typeof(int))),
Expression.SwitchCase(Expression.Constant("One"), Expression.Constant(1, typeof(int)))),
value
).Compile();
Console.WriteLine(meth(0)); // Zero
Console.WriteLine(meth(1)); // One
Console.WriteLine(meth(2)); // 2
這裏SwitchExpression
返回一個值,這是一件好事switch
不能做。
因此,正如能夠做一些事情SwitchExpression
並不意味着你可以用switch
做,所以也沒有理由認爲能夠做什麼用switch
意味着你可以用SwitchExpression
做。
這麼說,我明白爲什麼SwitchExpression
也許是這樣設置的,不同之處在於它簡化了其中一個表達式沒有的情況下和沒有默認的身體情況沒有充分的理由。也就是說,我認爲這可能只是表達一般意圖有多個案件的表達問題,而這正是編碼要支持的內容。
我已經submitted a pull-request to .NET Core將允許這樣的情況下,較少的表達式,通過產生SwitchExpression
其中用於的switchValue
的類型的默認值具有相同的主體作爲默認體。這種方法意味着任何會被SwitchExpression
感到驚訝的事情,沒有任何情況下仍然可以應付,避免向後兼容性問題。沒有缺省的情況通過創建noop表達式來處理,因此現在仍然拋出ArgumentException
的唯一情況是如果沒有情況和沒有缺省和該類型被明確地設置爲除了void
之外的東西,這種情況在打印規則中是無效的,這些打印規則顯然仍然應該保留。
[更新:這種做法遭到了拒絕,但a later pull-request被接受,所以現在無外殼SwitchExpression
S被.NET核心允許的,但如果當由.NET的其他版本採用的是另一回事。
與此同時,或者如果您使用另一個版本的。NET,你最好關閉使用一個輔助方法,如:
public static Expression SwitchOrDefault(Type type, Expression switchValue, Expression defaultBody, MethodInfo comparison, IEnumerable<SwitchCase> cases)
{
if (cases != null)
{
// It's possible that cases is a type that can only be enumerated once.
// so we check for the most obvious condition where that isn't true
// and otherwise create a ReadOnlyCollection. ReadOnlyCollection is
// chosen because it's the most efficient within Switch itself.
if (!(cases is ICollection<SwitchCase>))
cases = new ReadOnlyCollection<SwitchCase>(cases);
if (cases.Any())
return Switch(type, switchValue, defaultBody, comparison, cases);
}
return Expression.Block(
switchValue, // include in case of side-effects.
defaultBody != null ? defaultBody : Expression.Empty() // replace null with a noop expression.
);
}
過載,如:
public static Expression SwitchOrDefault(Expression switchValue, Expression defaultBody, params SwitchCase[] cases)
{
return SwitchOrDefault(switchValue, defaultBody, null, (IEnumerable<SwitchCase>)cases);
}
等等然後可以加入。
這會導致一個整數Expression
總比我的拉動請求,因爲它完全刪除了switch
在無情況下,只是返回默認正文。如果你確實需要有一個SwitchExpression
那麼你可以創建一個類似的幫助方法,該方法遵循與創建新的SwitchCase
然後使用它的請求相同的邏輯。
這樣的建築的目標是什麼? ''開關''默認',沒有'case'只是執行'默認' – 2015-02-06 07:43:00
對於我來說,沒有案例的切換看起來很沒意義,所以我認爲這個例外是合理的。 – 2015-02-06 07:43:01
是的,C#規範說一個開關塊有零個或多個開關部分;但這並不意味着開關表達式必須與C#規範混淆。由於您在運行時創建了表達式,因此您可以作爲解決方法簡單地添加一個「Expression.SwitchCase」,其值爲!=開關值;或者將默認情況下的主體添加爲開關值,其值爲開關值。 – sloth 2015-02-06 11:25:27