2012-01-21 9 views
32

मैं सिर्फ यह जानना चाहता हूं कि वास्तव में एक enum ध्वज सेट है, जो नहीं। मेरी वर्तमान सोच यह जांचना है कि यह 2 की शक्ति है या नहीं। क्या एनम प्रकारों में एक बेहतर तरीका बनाया गया है?मैं कैसे जांचूं कि एक से अधिक enum ध्वज सेट है या नहीं?

[Flags] 
enum Foo 
{ 
Flag1 = 0x01, 
Flag2 = 0x02, 
Flag3 = 0x04, 
Flag4 = 0x08, 
Flag5 = 0x10, 
Flag6 = 0x20, 
Flag7 = 0x40, 
Flag8 = 0x80 
} 

private bool ExactlynOneFlagSet(Foo myFoo) 
{ 
    var x = (byte) myFoo; 
    return (x != 0) && ((x & (x - 1)) == 0); //Check if a power of 2 
} 

if(!ExactlynOneFlagSet(Foo myFoo)) 
{ 
    //Do something 
} 
+0

यह बहुत आसान लगता है, हाँ। ऐसा क्यों नहीं करते? – Groo

+2

कृपया अपने शीर्षक को "सी #:" और इस तरह से उपसर्ग न करें। यही टैग है। –

+0

मुझे यह महसूस क्यों हो रहा है कि यह एक प्रश्न के रूप में छिपी हुई प्रश्न "मेरे समाधान को देखो" प्रश्न है ... –

उत्तर

10
private bool ExatlyOneFlagSet(Foo myFoo) 
{ 
    return !myFoo.ToString().Contains(','); 
} 
+1

@ मार्कहाल इन।नेट अगर एक से अधिक झंडा सेट किया गया है, तो enum का स्ट्रिंग प्रस्तुति एक अल्पविराम-सीमित सूची है। –

+1

@MarkHall ध्वज विशेषता इसे अल्पविराम से अलग व्यक्तिगत मान नाम दिखाती है। आप आगे बढ़ सकते हैं और कोशिश कर सकते हैं। – itsme86

+0

मैं –

7

enum झंडे के स्पष्ट संयोजन को परिभाषित नहीं करता, तो आप सिर्फ देख सकते हैं कि मूल्य enum में परिभाषित किया गया है:

private bool ExactlynOneFlagSet(Foo myFoo) 
{ 
    return Enum.IsDefined(typeof(Foo), myFoo); 
} 
+0

डाउनवोट क्यों? –

+0

+1: यह काम करता है, भले ही enum स्पष्ट रूप से संयोजनों को परिभाषित करता है ('enum foo {none = 0, ए = 1, बी = 2, सी = 4, एबी = ए | बी, बीसी = बी | सी, ऑल = ए | बी | सी,} ')। पूर्वनिर्धारित संयोजनों में से एक निर्दिष्ट करना ('Enum.IsDefined (typeof (Foo), Foo.A | Foo.B)') 'सत्य' उत्पन्न करेगा: वास्तव में यह एक निर्धारित मान है। –

+0

@ निकोलस कैरी, हाँ, यह एबी के लिए सच हो जाएगा, लेकिन एबी में एक से अधिक बिट सेट हैं ... ओपी जानना चाहता है कि एक से अधिक बिट सेट हैं, न कि मूल्य परिभाषित किया गया है। –

52

यह एक बिट आपरेशन!

if ((myFoo & (myFoo -1)) != 0) //has more than 1 flag 

बयान जांच करता है कि myFoo का मूल्य दो की शक्ति नहीं है। या, इसके विपरीत, कथन (myFoo & (myFoo -1)) == 0 दो की शक्ति के लिए जांच करता है। विचार यह है कि केवल एक ध्वज मूल्य दो की शक्ति होगी। एक से अधिक ध्वज सेट करने के परिणामस्वरूप myFoo के दो मानों की एक गैर शक्ति होगी।

अधिक जानकारी इस उत्तर में एक ही प्रश्न के उत्तर में मिल सकती है: https://stackoverflow.com/a/1662162/2404788

बिट संचालन के बारे में अधिक जानकारी के लिए http://en.wikipedia.org/wiki/Bitwise_operation

+3

+1, बहुत ही सुरुचिपूर्ण समाधान! –

+0

@ गुइडो ग्रेट सॉल्यूशन। क्या आप कृपया कुछ स्पष्टीकरण जोड़ सकते हैं? – Shimmy

+0

धन्यवाद @Shimmy। मैंने एक बुनियादी स्पष्टीकरण जोड़ा है। उम्मीद है कि यह उपयोगी है –

0

करने के लिए जाना याकूब के रूप में एक टिप्पणी अपने विधि बिल्कुल सही नहीं है में विस्तार से बताया। व्यक्तिगत रूप से मैं हमेशा गणितीय प्रोग्रामिंग से बचता हूं, खासकर जब तर्क की बात आती है। तो मेरा समाधान कुछ ऐसा होगा जैसे "अगर मैं जानना चाहता था कि गिनती एक है, तो इसे गिनें और इसकी तुलना एक नंबर पर करें"।

संदेश यह है:

public static bool OneIsSet(Type enumType, byte value) 
    { 
     return Enum.GetValues(enumType).Cast<byte>().Count(v => (value & v) == v) == 1; 
    } 

    public static bool OneIsSet(Type enumType, int value) 
    { 
     return Enum.GetValues(enumType).Cast<byte>().Count(v => (value & v) == v) == 1; 
    } 

और तुम इस तरह अपने foo प्रकार के लिए उपयोग कर सकते हैं:

var toReturnFalse = (byte)(foo.Flag1 | foo.Flag2); 
    var toReturnTrue = (byte)foo.Flag1; 
    var trueWillBeReturned = OneIsSet(typeof(foo), toReturnTrue); 
    var falseWillBeReturned = OneIsSet(typeof(foo), toReturnFalse); 

मेरा मानना ​​है कि यह तरीकों जेनेरिक्स और प्रकार का उपयोग कर एक अधिक सामान्य तरीके से लिखा जा सकता है हैंडलिंग विधियों। हालांकि मैंने इंट और बाइट इंटम्स के लिए सबसे आम आधार प्रकारों के तरीकों को शामिल किया। लेकिन आप इसे छोटे और अन्य प्रकार के लिए भी लिख सकते हैं। इसके अलावा आप अपने कोड में कोड को रेखांकित भी कर सकते हैं। यह कोड की केवल एक पंक्ति है।

इस विधि का उपयोग करके आप देख सकते हैं कि सेट झंडे की संख्या दो या अधिक है या नहीं। सेट झंडे की गिनती 'एन' के बराबर होती है, तो नीचे दिया गया कोड सत्य लौटाता है।

Enum.GetValues(enumType).Cast<byte>().Count(v => (value & v) == v) == n; 
संबंधित मुद्दे