2012-02-15 22 views
5

में प्लस ऑपरेटर आज मैं एक एनम परिभाषा में प्लस (+) ऑपरेटर के उपयोग पर ठोकर खा गया, मैं साथ में परीक्षण परीक्षणों को देखकर आश्चर्यचकित हुआ। किसी को भी कोई विचार है जहां इसे दस्तावेज किया जा सकता है?एनम परिभाषा

public enum ApprovalItemState 
{ 
    Enqueued = 1, 
    Approved = 2, 
    Denied = 4, 
    Acknowledged = 8, 
    ApprovalAcknowledged = ApprovalItemState.Approved + ApprovalItemState.Acknowledged, 
    DenialAcknowledged = ApprovalItemState.Denied + ApprovalItemState.Acknowledged 
} 


[TestClass] 
public class ApprovalItemStateTests 
{ 
    [TestMethod] 
    public void AreFlagsDeniedAndAcknowledged() 
    { 
     Assert.AreEqual(ApprovalItemState.DenialAcknowledged, ApprovalItemState.Denied | ApprovalItemState.Acknowledged); 
    } 

    [TestMethod] 
    public void IsDenialAcknowledged() 
    { 
     Assert.IsTrue(Enum.IsDefined(typeof(ApprovalItemState), ApprovalItemState.Denied | ApprovalItemState.Acknowledged)); 
     Assert.AreEqual(ApprovalItemState.Denied | ApprovalItemState.Acknowledged, (ApprovalItemState)Enum.Parse(typeof(ApprovalItemState), "DenialAcknowledged")); 
    } 


    [TestMethod] 
    public void IsNotDeniedAndApproved() 
    { 
     Assert.IsFalse(Enum.IsDefined(typeof(ApprovalItemState), ApprovalItemState.Approved | ApprovalItemState.Denied)); 
    } 
} 
+7

ऐसा इसलिए है क्योंकि enum मान केवल डिफ़ॉल्ट रूप से Int32 मान हैं। अगर कोडर इस्तेमाल होता तो यह बेहतर होगा (बिट या) इसके बजाय, मुझे लगता है। –

+0

@DanielPratt थोड़ा सा फिसल गया, जिसे उत्तर के रूप में भी पोस्ट किया जा सकता है। :) –

+0

मुझे लगता है कि आपको थोड़ा सा उपयोग करना चाहिए या इसके बजाय, यदि आप इस enum को ध्वज के रूप में उपयोग करना चाहते हैं तो यह सहायक हो सकता है: http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx – 0lukasz0

उत्तर

10

सी # भाषा युक्ति, 14.5 में, राज्यों:

निम्नलिखित ऑपरेटरों enum प्रकार के मूल्यों पर इस्तेमाल किया जा सकता: ==, =, <,>, < =,> = (§ 7.10.5), बाइनरी + (§7.8.4), बाइनरी - (§7.8.5), ^, &, | (§7.11.2), ~ (§7.7.4), ++ और - (§7.6.9 और §7.7.5)।

मूल रूप से, के बाद से enum आंतरिक रूप से (जब तक आप एक अलग भंडारण प्रकार निर्दिष्ट है कि, डिफ़ॉल्ट है) एक Int32 के रूप में संग्रहीत किया जाता है, तो आप इस तरह के अलावा उपयोग कर सकते हैं।

हालांकि, मास्क को परिभाषित करने के लिए + के बजाय | का उपयोग करना कहीं अधिक आम है। इसके अलावा, यदि आप इसे झंडे के रूप में उपयोग करने जा रहे हैं तो [Flags] शामिल करना आम होगा।

+0

I लगता है कि '[ध्वज]' का उपयोग नहीं किया जा रहा है क्योंकि कुछ राज्य तकनीकी रूप से तार्किक नहीं होंगे। – Dave

+1

@ डेव: ध्वज विशेषता का उपयोग न करने का यह एक भयानक कारण है। –

+0

@MarkByers देखभाल करने के लिए देखभाल? – Dave

2

the C# reference on enum से:

... हर गणना प्रकार एक अंतर्निहित प्रकार है, जो चार को छोड़कर किसी भी अभिन्न प्रकार हो सकता है। गणन तत्वों की डिफ़ॉल्ट अंतर्निहित प्रकार यह (त्रुटि होने का खतरा और कम) | बजाय + उपयोग करने के लिए enum फ़्लैग मान गठबंधन करने के लिए और अधिक मुहावरेदार है पूर्णांक है ...

वैसे,। उदाहरण के लिए, इस गलती को एक समस्या का कारण नहीं बनेगा:

DenialAcknowledged = 
    ApprovalItemState.Denied 
    | ApprovalItemState.Acknowledged 
    | ApprovalItemState.Denied 

लेकिन इस गलती एक समस्या का कारण होगा:

DenialAcknowledged = 
    ApprovalItemState.Denied 
    + ApprovalItemState.Acknowledged 
    + ApprovalItemState.Denied 
0

यह आश्चर्य की बात नहीं कर रहा है - enums अभिन्न प्रकार का प्रतिनिधित्व कर रहे। आप अन्य ऑपरेटरों का भी उपयोग कर सकते हैं, हालांकि यदि आप झंडे का उपयोग करने जा रहे हैं (जो यह उदाहरण कर रहा है), तो उन्हें परिभाषित करने के लिए [ध्वज] विशेषता का उपयोग करना बेहतर है और बिट्स को अधिक स्पष्ट रूप से बाहर रखना बेहतर है:

[Flags] 
public enum ApprovalItemState 
{ 
    Enqueued = 1 << 0, 
    Approved = 1 << 1, 
    Denied = 1 << 2, 
    Acknowledged = 1 << 3, 
    ApprovalAcknowledged = ApprovalItemState.Approved | ApprovalItemState.Acknowledged, 
    DenialAcknowledged = ApprovalItemState.Denied | ApprovalItemState.Acknowledged 
} 
1

Approved + Acknowledged केवल स्थिर है इसलिए इसे enum तत्व के मान के रूप में असाइन किया जा सकता है। के बारे में परीक्षण - वे काम करते हैं क्योंकि पूर्णांक मूल्यों "खुश लोगों" हैं, इसलिए (a + b) == (a | b)

हालांकि अपने परिवर्तन ऐसा ही कुछ करने के लिए है कि अगर:

public enum ApprovalItemState 
{ 
    Enqueued = 1, 
    Approved = 2, 
    Denied = 7, 
    Acknowledged = 18, 
    ApprovalAcknowledged = Approved + Acknowledged, 
    DenialAcknowledged = Denied + Acknowledged 
} 

और परीक्षण पास नहीं होंगे।

0

मैं आपके लिए इनमें से एक को तोड़ दूंगा।

DenialAcknowledged = ApprovalItemState.Denied + ApprovalItemState.Acknowledged 
DenialAcknowledged = 4 + 8 
DenialAcknowledged = 12 

इस परीक्षण के लिए:

[TestMethod] 
public void AreFlagsDeniedAndAcknowledged() 
{ 
    Assert.AreEqual(ApprovalItemState.DenialAcknowledged, ApprovalItemState.Denied | ApprovalItemState.Acknowledged); 
} 

आप जाँच कर रहे हैं:

ApprovalItemState.DenialAcknowledged == ApprovalItemState.Denied | ApprovalItemState.Acknowledged 
12 == 4 | 8 
12 == 0100 | 1000 //bitwise operation 
12 == 1100 
12 == 12 //convert from binary to decimal 

और यही कारण है परीक्षण पास होना जरूरी है। कोड को देखकर बिल्कुल सरल नहीं है।

11

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

public enum ApprovalItemState 
{ 
    Enqueued = 1, 
    Approved = 2, 
    Denied = 4, 
    Acknowledged = 8, 
    ApprovalAcknowledged = Approved | Acknowledged, 
    DenialAcknowledged = Denied | Acknowledged 
} 

दूसरा सामान्य ज्ञान का कहना है कि सी # संकलक वास्तव में अनुमति देता है enum अंकगणित अन्य enums एक enum अंदर से जुड़े है!

enum E 
{ 
    E1 
} 
enum F 
{ 
    F1 
} 
enum G 
{ 
    G1 = E.E1 + F.F1 
} 

आम तौर पर है कि सभी कानूनी पर नहीं होगा, आप एक साथ दो अलग-अलग enums जोड़ नहीं सकते हैं और आप परिणाम असाइन नहीं कर सकते हैं। कंपाइलर एक नियम प्रारंभकर्ता के अंदर उन नियमों को आराम देता है ताकि आप चीजें कर सकें:

enum MyFlags 
{ 
    MyReadOnly = FileFlags.ReadOnly, 
    ...