c# - समय - सबसे पहले तिरंगा किसने फहराया




सी#में झंडे की तुलना कैसे करें? (8)

मेरे पास नीचे एक झंडा enum है।

[Flags]
public enum FlagTest
{
    None = 0x0,
    Flag1 = 0x1,
    Flag2 = 0x2,
    Flag3 = 0x4
}

अगर मैं कथन का सही मूल्यांकन नहीं कर सकता हूं।

FlagTest testItem = FlagTest.Flag1 | FlagTest.Flag2;

if (testItem == FlagTest.Flag1)
{
    // Do something,
    // however This is never true.
}

मैं यह कैसे सच कर सकता हूं?


.NET 4 में एक नई विधि Enum.HasFlag । यह आपको लिखने की अनुमति देता है:

if ( testItem.HasFlag( FlagTest.Flag1 ) )
{
    // Do Stuff
}

जो बहुत अधिक पठनीय, आईएमओ है।

.NET स्रोत इंगित करता है कि यह स्वीकार्य उत्तर के समान तर्क करता है:

public Boolean HasFlag(Enum flag) {
    if (!this.GetType().IsEquivalentTo(flag.GetType())) {
        throw new ArgumentException(
            Environment.GetResourceString(
                "Argument_EnumTypeDoesNotMatch", 
                flag.GetType(), 
                this.GetType()));
    }

    ulong uFlag = ToUInt64(flag.GetValue()); 
    ulong uThis = ToUInt64(GetValue());
    // test predicate
    return ((uThis & uFlag) == uFlag); 
}

@ फिल-Devaney

ध्यान दें कि मामलों के सबसे सरलतम को छोड़कर, Enum.HasFlag मैन्युअल रूप से कोड लिखने की तुलना में भारी प्रदर्शन जुर्माना रखता है। निम्नलिखित कोड पर विचार करें:

[Flags]
public enum TestFlags
{
    One = 1,
    Two = 2,
    Three = 4,
    Four = 8,
    Five = 16,
    Six = 32,
    Seven = 64,
    Eight = 128,
    Nine = 256,
    Ten = 512
}


class Program
{
    static void Main(string[] args)
    {
        TestFlags f = TestFlags.Five; /* or any other enum */
        bool result = false;

        Stopwatch s = Stopwatch.StartNew();
        for (int i = 0; i < 10000000; i++)
        {
            result |= f.HasFlag(TestFlags.Three);
        }
        s.Stop();
        Console.WriteLine(s.ElapsedMilliseconds); // *4793 ms*

        s.Restart();
        for (int i = 0; i < 10000000; i++)
        {
            result |= (f & TestFlags.Three) != 0;
        }
        s.Stop();
        Console.WriteLine(s.ElapsedMilliseconds); // *27 ms*        

        Console.ReadLine();
    }
}

10 मिलियन से अधिक पुनरावृत्तियों, मानक बिटवाई कार्यान्वयन के लिए 27 एमएस की तुलना में हैस्फ्लैग एक्सटेंशन विधि में 47 9 3 एमएस की भारी मात्रा है।


उन लोगों के लिए जिन्हें स्वीकार्य समाधान (जो यह है) के साथ क्या हो रहा है, कल्पना करने में परेशानी है,

if ((testItem & FlagTest.Flag1) == FlagTest.Flag1)
{
    // Do stuff.
}

testItem (प्रश्न के अनुसार) के रूप में परिभाषित किया गया है,

testItem 
 = flag1 | flag2  
 = 001 | 010  
 = 011

फिर, अगर कथन में, तुलना के बाएं हाथ की तरफ है,

(testItem & flag1) 
 = (011 & 001) 
 = 001

और पूर्ण अगर कथन (जो testItem में testItem 1 सेट किया गया है तो सत्य का मूल्यांकन करता है)

(testItem & flag1) == flag1
 = (001) == 001
 = true

बिट ऑपरेशंस के लिए, आपको बिटवाई ऑपरेटरों का उपयोग करने की आवश्यकता है।

यह काम कर जाना चाहिए:

if ((testItem & FlagTest.Flag1) == FlagTest.Flag1)
{
    // Do something,
    // however This is never true.
}

संपादित करें: अगर मेरा चेक फिक्स्ड - मैं अपने सी / सी ++ तरीकों से वापस फिसल गया (रयान फर्ले को धन्यवाद देने के लिए धन्यवाद)


यहां तक ​​कि [झंडे] के बिना, आप इस तरह कुछ उपयोग कर सकते हैं

if((testItem & (FlagTest.Flag1 | FlagTest.Flag2 ))!=0){
//..
}

या यदि आपके पास शून्य मूल्य enum है

if((testItem & (FlagTest.Flag1 | FlagTest.Flag2 ))!=FlagTest.None){
//..
}

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

अर्थात

public class FlagTestCompare
{
    public static bool Compare(this FlagTest myFlag, FlagTest condition)
    {
         return ((myFlag & condition) == condition);
    }
}

if ((testItem & FlagTest.Flag1) == FlagTest.Flag1)
{
     // Do something
}

(testItem & FlagTest.Flag1) और ऑपरेशन है।

FlagTest.Flag1 ओपी के enum के साथ 001 बराबर है। अब testItem लें कि testItem में Flag1 और Flag2 है (इसलिए यह bitwise 101 ):

  001
 &101
 ----
  001 == FlagTest.Flag1

if((testItem & FlagTest.Flag1) == FlagTest.Flag1) 
{
...
}




flags