वहाँ एक पूरा सादृश्य नहीं है सी # के 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
द्वारा किसी भी मामले को आश्चर्यचकित किया जाएगा, बिना किसी मामले को पीछे-संगतता समस्याओं से परहेज करना चाहिए। कोई डिफ़ॉल्ट नहीं होने का मामला या तो नोप अभिव्यक्ति बनाकर निपटाया जाता है जो कुछ भी नहीं करता है, इसलिए एकमात्र मामला जो अब भी ArgumentException
फेंकता है, यदि कोई मामला और कोई डिफ़ॉल्ट और प्रकार स्पष्ट रूप से सेट है void
के अलावा कुछ और, यह मामला टाइपिंग नियमों के तहत अमान्य है जिसे स्पष्ट रूप से अभी भी रखा जाना चाहिए।
[अपडेट: यह दृष्टिकोण को अस्वीकार कर दिया गया था, लेकिन a later pull-request स्वीकार कर लिया गया है, तो केस-कम SwitchExpression
रों अब हालांकि अगर और जब वह यह है कि एक और बात नेट के अन्य संस्करणों ने भी अपनाया है, नेट कोर द्वारा अनुमति दी जाती है।]
इस बीच, या यदि आप किसी अन्य संस्करण का उपयोग करते हैं।
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.
);
}
Overloads की तरह:
public static Expression SwitchOrDefault(Expression switchValue, Expression defaultBody, params SwitchCase[] cases)
{
return SwitchOrDefault(switchValue, defaultBody, null, (IEnumerable<SwitchCase>)cases);
}
और इसी तरह तो जोड़ा जा सकता है नेट, आप सबसे अच्छा बंद की तरह एक सहायक विधि का उपयोग कर रहे हैं।
यह मेरे पुल अनुरोध के मुकाबले एक ट्रिमर Expression
में परिणाम देता है, क्योंकि यह switch
पूरी तरह से नो-केस केस में कट करता है और केवल डिफ़ॉल्ट निकाय देता है। यदि आप वास्तव में को SwitchExpression
रखने की आवश्यकता है तो आप एक समान सहायक विधि बना सकते हैं जो उसी तर्क का अनुसरण करता है क्योंकि पुल-अनुरोध नया SwitchCase
बनाने में और उसके बाद इसका उपयोग करता है।
ऐसे निर्माण का लक्ष्य क्या है? 'डिफ़ॉल्ट' के साथ 'स्विच'' और 'केस' सिर्फ 'डिफ़ॉल्ट' –
निष्पादित करेगा मेरे लिए बिना किसी मामले के स्विच स्विच करना बहुत अर्थहीन दिखता है, इसलिए मुझे लगता है कि यह अपवाद उचित है। –
हां, सी # स्पेक का कहना है कि स्विच-ब्लॉक में शून्य या अधिक स्विच-सेक्शन हैं; लेकिन इसका मतलब यह नहीं है कि एक स्विच अभिव्यक्ति को सी # spec तक सीमित करना है। चूंकि आप रनटाइम पर अभिव्यक्ति बनाते हैं, तो आप एक वर्कअराउंड के रूप में, एक 'Expression.SwitchCase' को उस मान के साथ जोड़ सकते हैं! = स्विच वैल्यू; या वैल्यू = स्विच वैल्यू के साथ स्विच केस के रूप में डिफॉल्ट केस का बॉडी जोड़ें। – sloth