2015-11-19 42 views
5

पर अपेक्षित के रूप में कार्य नहीं कर रहा है यह एक quirky है।यदि संयुक्त एनम मूल्य

मैं निम्नलिखित कोड है ...

foreach (IScanTicket ticket in this) { 
    if (ticket.Status == TicketStatus.Created || ticket.Status == (TicketStatus.Transfered | TicketStatus.Created)) 
     return ticket; 
    } 
} 

जब मैं इस चलाने के लिए, स्थिति Created|Transferred वह जगह है जहाँ, अगर बयान विफल (क्या यह लगता है ऐसा नहीं) लगता है।

दिलचस्प बात यह है कि यदि मैं कोड को डीबग करता हूं और कथन देखता हूं, तो यह हमेशा मेरे डीबगर में TRUE देता है, फिर भी जब मैं कोड से कदम उठता हूं तो ब्लॉक में प्रवेश करने में विफल रहता है।

डीबगर क्यों दिखाता है कि कथन true है, फिर भी जारी है जैसे यह नहीं है? ऐसा लगता है कि डीबगर मुझे फाइब्स कह रहा है।

क्या किसी ने कभी इसका अनुभव किया है?

पीएस मैं Xamarin स्टूडियो का उपयोग कर रहा हूँ 5.9.7

+1

'टिकटस्टैटस 'कैसा है? क्या यह 'झंडे] विशेषता के साथ एक enum है? – MarcinJuraszek

+0

'टिकट' स्थिति का मूल्य क्या होता है जब यह विफल रहता है, लेकिन आप उम्मीद करते हैं कि 'सत्य' होना चाहिए? –

+0

दिलचस्प ... अगर मैं enum को चारों ओर शामिल करता हूं (उदाहरण के लिए। '(टिकटस्टैटस.क्रेटेड | टिकटस्टैटस। ट्रांसफर) ") ऐसा लगता है। Enum होने के नाते एक 'बाइट' ध्वज आधारित आधारित enum है, मैंने सोचा होगा कि इससे कोई फर्क नहीं पड़ता? .. कोई विचार क्यों? –

उत्तर

0

@MarcinJuraszek और @YeldarKurmangaliyev के लिए धन्यवाद।

[Flags] विशेषता एनम पर सेट नहीं किया गया था जैसा कि मैंने मूल रूप से सोचा था। इस विशेषता को जोड़ना अब enum काम को संयोजन में बनाता है।

तो ऐसा लगता है कि इस विशेषता को शामिल नहीं होने के कारण एनम मूल्यों का क्रम प्रभाव पड़ता है।

+0

हार्डकोड किए गए मानों के बिना एम्स ऑटो नंबर स्वयं। ध्वज enum के साथ मूल्यों को स्पष्ट रूप से परिभाषित करने के लिए यह बेहतर अभ्यास है। जैसे 0, 0x1, 0x2, 0x4, 0x8, 0x16, 0x32, 0x64 .. आदि। यदि आप मूल्यों को कड़ी मेहनत करते हैं तो यह काम करेगा चाहे उसके पास [ध्वज] है या नहीं। उन्हें हार्डकोडिंग नहीं करना बाद में आपको काट सकता है, क्योंकि यदि आप मौजूदा मानों के बीच में एक नया मान जोड़ते हैं तो यह पुराने मानों को ऑफ़सेट करेगा, जो आपके डेटा को खराब कर सकता है (उदाहरण के लिए डेटाबेस में) और स्कीड परिणाम को उस लाइन के नीचे उत्पन्न करेगा समस्या निवारण के लिए स्पष्ट नहीं है। –

+0

@Ryios यदि आप डेटाबेस में enum मान संग्रहीत कर रहे हैं, तो उन्हें हमेशा हार्डकोड करना एक अच्छा विचार है। यदि आप नहीं हैं, तो इसका कोई कारण नहीं है। – Amasa

+0

मैं हमेशा कड़ी मेहनत करता हूं अगर संकलक ऐसा नहीं करता है। तकनीकी रूप से मेरा कोड सही था, लेकिन वास्तव में संकलक कुछ और सोच रहा था। मैं बस इसे देखने के लिए कंपाइलर और जाल में एक quirk करने के लिए नीचे जा रहा हूँ। मैं इस बिंदु पर क्यों समझा सकता हूं, लेकिन जब मैंने '[झंडे] विशेषता को जोड़ा, तो यह अपेक्षा के अनुसार व्यवहार करना शुरू कर दिया। @ साएब-अमिनी की तरह, यह हो सकता है कि यह हैसफ्लैग() विधि का उपयोग करना बेहतर हो, लेकिन पुराना स्कूल सी ++ होने के नाते, मैं आमतौर पर बिटवॉइड कोडिंग में अपनी जड़ों पर वापस जाता हूं। :) –

3

एक टिप्पणी के लिए बहुत लंबा:

वास्तव में, [Flags] विशेषता एक enum का अर्थ विज्ञान बिल्कुल नहीं बदलता है, यह सबसे लोकप्रिय ToString विधि द्वारा प्रयोग किया जाता है बल्कि एक संयुक्त मूल्य के लिए एक नंबर से नामों की एक श्रृंखला फेंकना ।

मान लें कि आपका enum (Flags विशेषता के बिना) इस तरह घोषित किया गया था दो:

enum TicketStatus 
{ 
    Created = 1, 
    Transferred = 2, 
    Sold = 4 
} 

तुम अब भी विभिन्न सदस्यों को संयोजित करके झंडे enum पर लागू होता है कि किसी भी गणित कर सकता है:

TicketStatus status = TicketStatus.Created | TicketStatus.Transferred; 

हालांकि, निम्नलिखित प्रिंट करेंगे:

Console.WriteLine(status); 

लेकिन यदि आप [Flags] विशेषता जोड़ते हैं, तो यह Created, Transferred प्रिंट करेगा।

इसके अलावा, यह ध्यान रखें कि TicketStatus.Created | TicketStatus.Transferred से तुम सच में अंतर्निहित पूर्णांक मान पर एक बिटवाइज़ OR कर रहे हैं महत्वपूर्ण है, ध्यान दें कि किस हमारे उदाहरण में जो नियत मूल्यों स्पष्ट combinable हैं:

Created : 0001 
Transferred: 0010 
Sold:  0100 

इसलिए एक मूल्य को Created और Transferred के संयोजन के रूप में निर्विवाद रूप से निर्धारित किया जा सकता है।लेकिन अगर हम इस किया था:

enum TicketStatus 
{ 
    Created = 1,  // 0001 
    Transferred = 2, // 0010 
    Sold = 3,   // 0011 
} 

यह बाइनरी अभ्यावेदन द्वारा स्पष्ट है, मूल्यों के संयोजन और सदस्यों के खिलाफ जाँच समस्याग्रस्त है के रूप में संयुक्त सदस्यों अस्पष्ट हो सकता है के रूप में। जैसे status क्या है?

status = TicketStatus.Created | TicketStatus.Transferred; 

यह Created, Transferred है या यह वास्तव में Sold है? हालांकि, यदि आप इसे करने का प्रयास करते हैं तो संकलक शिकायत नहीं करेगा, जिससे आपकी तरह की बग को ट्रैक करने में कठिनाई हो सकती है, जहां कुछ चेक काम नहीं कर रहे हैं, जैसा कि आप उम्मीद करते हैं, इसलिए यह सुनिश्चित करना आपके लिए परिभाषा है थोड़ा सा मिश्रण और तुलना करना।

:

एक संबंधित नोट पर, के बाद से अपने if बयान वास्तव में केवल जाँच कर रहा है, तो टिकट एक Created का दर्जा प्राप्त है, की परवाह किए बिना अन्य सदस्यों के साथ संयुक्त किया जा रहा है, यहाँ के लिए कि (.NET> = 4) की जांच करने के लिए एक बेहतर तरीका है

status.HasFlag(TicketStatus.Created) 

या (.NET < 4):

(status & TicketStatus.Created) != 0 

क्यों अपने enum अपेक्षा के अनुरूप काम नहीं किया था के रूप में, यह लगभग निश्चित रूप से, क्योंकि आप स्पष्ट रूप से मैं करने के लिए unambigously बिटवाइज़ combinable मान निर्दिष्ट नहीं किया है टीएस सदस्यों (आमतौर पर दो की शक्तियां)।

+0

बिल्कुल, और इस तरह मैं इसे समझता हूं। यही वजह है कि यह मुझे भ्रमित कर रहा था कि यह क्यों काम नहीं कर रहा था। तकनीकी रूप से आप स्पॉट पर हैं, लेकिन जो मुझे मिल रहा था वह वास्तव में तब तक नहीं था जब तक कि मैं '[झंडे] विशेषता नहीं जोड़ता। इसलिए सवाल है। यह जानना दिलचस्प होगा कि कंपाइलर/जेआईटी क्या सोच रहा था क्योंकि डीबगर मुझे बता रहा था कि आपने क्या बताया है। –

+0

रास्ते से अच्छा और स्पष्ट लिखो। :) –