c# - हर संभव संयोजन की घोषणा किए बिना Enum(झंडे विशेषता के साथ) पर स्विच करें?




enums switch-statement (6)

मैं एक एनुम पर कैसे स्विच कर सकता हूं जिसमें झंडे विशेषता सेट है (या बिट संचालन के लिए अधिक सटीक उपयोग किया जाता है)?

मैं सभी मामलों को स्विच में सक्षम होना चाहता हूं जो घोषित मूल्यों से मेल खाते हैं।

समस्या यह है कि अगर मेरे पास निम्न एनम है

[Flags()]public enum CheckType
{
    Form = 1,   
    QueryString = 2,
    TempData = 4,
}

और मैं इस तरह से एक स्विच का उपयोग करना चाहता हूं

switch(theCheckType)
{
   case CheckType.Form:
       DoSomething(/*Some type of collection is passed */);
       break;

   case CheckType.QueryString:
       DoSomethingElse(/*Some other type of collection is passed */);
       break;

   case CheckType.TempData
       DoWhatever(/*Some different type of collection is passed */);
       break;
}

यदि "theCheckType" दोनों CheckType.Form पर सेट है CheckType.TempData मैं चाहता हूं कि यह दोनों मामले में हिट हो। स्पष्ट रूप से यह ब्रेक के कारण मेरे उदाहरण में दोनों नहीं मारा, लेकिन इसके अलावा यह भी विफल रहता है क्योंकि CheckType.Form CheckType.Form के बराबर नहीं है | CheckType.TempData

एकमात्र समाधान तब जैसा कि मैं देख सकता हूं कि एनम मूल्यों के हर संभव संयोजन के लिए एक मामला बनाना है?

कुछ इस तरह

    case CheckType.Form | CheckType.TempData:
        DoSomething(/*Some type of collection is passed */);
        DoWhatever(/*Some different type of collection is passed */);
        break;

    case CheckType.Form | CheckType.TempData | CheckType.QueryString:
        DoSomething(/*Some type of collection is passed */);
        DoSomethingElse(/*Some other type of collection is passed */);
        break;

... and so on...

लेकिन यह वास्तव में बहुत वांछित नहीं है (क्योंकि यह जल्दी से बहुत बड़ा हो जाएगा)

अभी मेरे पास 3 हैं अगर प्रत्येक के बजाय सही स्थिति

कुछ इस तरह

if ((_CheckType & CheckType.Form) != 0)
{
    DoSomething(/*Some type of collection is passed */);
}

if ((_CheckType & CheckType.TempData) != 0)
{
    DoWhatever(/*Some type of collection is passed */);
}

....

लेकिन इसका मतलब यह भी है कि अगर मेरे पास 20 मूल्यों के साथ एक एनम है, तो इसे 20 बार से गुजरना होगा यदि हर बार "कूद" के बजाय केवल "आवश्यक" मामले में "स्विच" का उपयोग करते समय।

क्या इस समस्या को हल करने के लिए कुछ जादुई उपाय है?

मैंने घोषित मूल्यों के माध्यम से लूप की संभावना के बारे में सोचा है और फिर स्विच का उपयोग किया है, तो यह केवल घोषित किए गए प्रत्येक मान के लिए स्विच को हिट करेगा, लेकिन मुझे नहीं पता कि यह कैसे काम करेगा और अगर यह प्रदर्शन ठीक है, तो यह एक अच्छा विचार है ( अगर की तुलना में बहुत अधिक है)?

घोषित किए गए सभी एनम वैल्यू के माध्यम से लूप करने का एक आसान तरीका है?

मैं केवल ToString () और "," और फिर विभाजन के माध्यम से बंटवारे का उपयोग करके आ सकता हूं और हर एक स्ट्रिंग को पार्स कर सकता हूं।

अद्यतन करें:

मैं देख रहा हूँ कि मैंने एक अच्छा पर्याप्त काम नहीं किया है। मेरा उदाहरण सरल है (मेरे परिदृश्य को सरल बनाने की कोशिश की गई है)।

मैं यह देखने के लिए Asp.net MVC में ActionMethodSelectorAttribute के लिए इसका उपयोग करता हूं कि क्या कोई विधि url / रूट को हल करते समय उपलब्ध होनी चाहिए।

मैं इसे विधि पर कुछ इस तरह घोषित करके करता हूं

[ActionSelectorKeyCondition(CheckType.Form | CheckType.TempData, "SomeKey")]
public ActionResult Index()
{
    return View();
} 

इसका मतलब यह होगा कि यह जाँचना चाहिए कि क्या फॉर्म या टेंपडाटा के पास उपलब्ध विधि के लिए निर्दिष्ट कुंजी है।

विधियाँ यह कह रही होंगी (doSomething (), doSomethingElse () और doWhatever () मेरे पिछले उदाहरण में) वास्तव में रिटर्न वैल्यू के रूप में बूल होंगे और उन्हें एक पैरामीटर (अलग-अलग संग्रह) के साथ बुलाया जाएगा जो एक इंटरफ़ेस साझा नहीं करता है जो कि हो सकता है इस्तेमाल किया - नीचे दिए गए लिंक में मेरा उदाहरण कोड देखें)।

उम्मीद करने के लिए कि मैं जो कर रहा हूं उसका एक बेहतर विचार दे सकता हूं कि मैंने वास्तव में पास्टबिन पर क्या कर रहा हूं, इसका एक सरल उदाहरण चिपकाया है - यह यहां पाया जा सकता है http://pastebin.com/m478cc2b8


C # 7 के साथ अब आप कुछ इस तरह लिख सकते हैं:

public void Run(CheckType checkType)
{
    switch (checkType)
    {
        case var type when CheckType.Form == (type & CheckType.Form):
            DoSomething(/*Some type of collection is passed */);
            break;

        case var type when CheckType.QueryString == (type & CheckType.QueryString):
            DoSomethingElse(/*Some other type of collection is passed */);
            break;

        case var type when CheckType.TempData == (type & CheckType.TempData):
            DoWhatever(/*Some different type of collection is passed */);
            break;
    }
}

C # 7 में संभव होना चाहिए

switch (t1)
    {
        case var t when t.HasFlag(TST.M1):
            {
                break;
            }
        case var t when t.HasFlag(TST.M2):
            {
                break;
            }

इस बारे में कैसा है। बेशक तर्कों और DoSomething के प्रकार, आदि, आप की तरह कुछ भी हो सकता है।

class Program
{
    [Flags]
    public enum CheckType
    {
        Form = 1,
        QueryString = 2,
        TempData = 4,
    }

    private static bool DoSomething(IEnumerable cln)
    {
        Console.WriteLine("DoSomething");
        return true;
    }

    private static bool DoSomethingElse(IEnumerable cln)
    {
        Console.WriteLine("DoSomethingElse");
        return true;
    }

    private static bool DoWhatever(IEnumerable cln)
    {
        Console.WriteLine("DoWhatever");
        return true;
    }

    static void Main(string[] args)
    {
        var theCheckType = CheckType.QueryString | CheckType.TempData;
        var checkTypeValues = Enum.GetValues(typeof(CheckType));
        foreach (CheckType value in checkTypeValues)
        {
            if ((theCheckType & value) == value)
            {
                switch (value)
                {
                    case CheckType.Form:
                        DoSomething(null);
                        break;
                    case CheckType.QueryString:
                        DoSomethingElse(null);
                        break;
                    case CheckType.TempData:
                        DoWhatever(null);
                        break;
                }
            }
        }
    }
}

एक Dictionary<CheckType,Action> जो आप भरेंगे

dict.Add(CheckType.Form, DoSomething);
dict.Add(CheckType.TempDate, DoSomethingElse);
...

आपके मूल्य का अपघटन

flags = Enum.GetValues(typeof(CheckType)).Where(e => (value & (CheckType)e) == (CheckType)e).Cast<CheckType>();

और फिर

foreach (var flag in flags)
{
   if (dict.ContainsKey(flag)) dict[flag]();
}

(कोड अप्राप्त)


बस HasFlag उपयोग HasFlag

if(theCheckType.HasFlag(CheckType.Form)) DoSomething(...);
if(theCheckType.HasFlag(CheckType.QueryString)) DoSomethingElse(...);
if(theCheckType.HasFlag(CheckType.TempData)) DoWhatever(...);

सबसे आसान तरीका है कि आप केवल एक ORed , अपने मामले में आप निम्न कार्य कर सकते हैं:

[Flags()]public enum CheckType
{
    Form = 1,   
    QueryString = 2,
    TempData = 4,
    FormQueryString = Form | QueryString,
    QueryStringTempData = QueryString | TempData,
    All = FormQueryString | TempData
}

एक बार जब आपके पास enum सेटअप होता है तो अपना switch स्टेटमेंट करने में आसानी होती है

जैसे, अगर मैंने निम्नलिखित निर्धारित किया है:

var chkType = CheckType.Form | CheckType.QueryString;

मैं निम्न switch स्टेटमेंट का उपयोग इस प्रकार कर सकता हूं:

switch(chkType){
 case CheckType.Form:
   // Have Form
 break;
 case CheckType.QueryString:
   // Have QueryString
 break;
 case CheckType.TempData:
  // Have TempData
 break;
 case CheckType.FormQueryString:
  // Have both Form and QueryString
 break;
 case CheckType.QueryStringTempData:
  // Have both QueryString and TempData
 break;
 case CheckType.All:
  // All bit options are set
 break;
}

बहुत क्लीनर और आपको HasFlag साथ एक स्टेटमेंट का उपयोग करने की आवश्यकता नहीं है। आप अपनी इच्छानुसार कोई भी संयोजन बना सकते हैं और फिर स्विच स्टेटमेंट को पढ़ना आसान बना सकते हैं।

मैं आपकी enums को तोड़ने की सलाह enums , यह देखने की कोशिश करूंगा कि क्या आप अलग-अलग चीजों को एक ही enum में नहीं मिला रहे हैं। आप मामलों की संख्या को कम करने के लिए कई enums सेटअप कर सकते हैं।







bit