एनुम परिभाषा में टिल्ड (~) क्या है?


149

मुझे हमेशा आश्चर्य होता है कि इस समय के लिए C # का उपयोग करने के बाद भी, मैं अभी भी उन चीजों को खोजने का प्रबंधन करता हूं जिनके बारे में मुझे नहीं पता था ...

मैंने इसके लिए इंटरनेट खोजने की कोशिश की है, लेकिन खोज में "~" का उपयोग करना मेरे लिए इतना अच्छा काम नहीं कर रहा है और मुझे MSDN पर कुछ भी नहीं मिला (ऐसा नहीं है कहने के लिए)

मैंने हाल ही में कोड के इस स्निपेट को देखा, टिल्ड (~) का क्या अर्थ है?

/// <summary>
/// Enumerates the ways a customer may purchase goods.
/// </summary>
[Flags]
public enum PurchaseMethod
{   
    All = ~0,
    None =  0,
    Cash =  1,
    Check =  2,
    CreditCard =  4
}

मैं इसे देखकर थोड़ा आश्चर्यचकित था इसलिए मैंने इसे संकलित करने की कोशिश की, और यह काम किया ... लेकिन मुझे अभी भी नहीं पता कि इसका क्या मतलब है / क्या करता है। कोई मदद??


4
यह एक भयानक और सुरुचिपूर्ण समाधान है जो समय के साथ एनम के सुचारू उन्नयन के लिए अनुमति देता है। दुर्भाग्य से यह CA-2217 के साथ संघर्ष करता है और यदि आप कोड विश्लेषण का उपयोग करते हैं, तो एक त्रुटि होगी :( msdn.microsoft.com/en-us/library/ms182335.aspx
जेसन

अब इसका 2020 है, और मैं खुद को उन्हीं शब्दों के रूप में सोच रहा हूं, जिनके साथ आप अपनी पोस्ट शुरू करते हैं। यह सुनकर खुशी हुई कि मैं अकेला नहीं हूं।
फुक्यूमिश्मरूम

जवाबों:


136

~ है एकतरफा पूरक ऑपरेटर - यह अपने ऑपरेंड के बिट्स को फ़्लिप करता है।

~0 = 0xFFFFFFFF = -1

दो पूरक अंकगणित में, ~x == -x-1

~ ऑपरेटर बहुत सी किसी भी भाषा में पाया जा सकता है जो C से उधार सिंटैक्स, उद्देश्य-सी / सी ++ / सी # / जावा / जावास्क्रिप्ट सहित।


यह अच्छा है। मुझे नहीं पता था कि आप ऐसा कर सकते हैं। भविष्य में निश्चित रूप से उपयोग करेंगे
ओरियन एडवर्ड्स

तो यह सभी = Int32.MaxValue के बराबर है? या UInt32.MaxValue?
जोएल मुलर

2
सभी = (अहस्ताक्षरित int) -1 == UInt32.MaxValue। Int32.MaxValue की कोई प्रासंगिकता नहीं है।
जिमी

4
@ Stevo3000: Int32.MinValue 0xF0000000 है, जो ~ 0 नहीं है (यह वास्तव में ~ Int32.MaxValue है)
जिमी

2
@ जिमी: Int32.MinValue 0x80000000 है। इसमें केवल एक ही बिट सेट है (चार नहीं जो एफ आपको देगा)।
ILMTitan

59

मुझे लगता है कि:

[Flags]
public enum PurchaseMethod
{
    None = 0,
    Cash = 1,
    Check = 2,
    CreditCard = 4,
    All = Cash | Check | CreditCard
 }

थोड़ा और स्पष्ट होगा।


10
यह निश्चित ही। यूनीरी का एकमात्र अच्छा प्रभाव यह है कि अगर किसी को एन्यूमरेशन में जोड़ा जाता है, तो सभी इसे स्वचालित रूप से शामिल करते हैं। फिर भी, लाभ स्पष्टता की कमी को दूर नहीं करता है।
ctacke

12
मैं नहीं देखता कि यह कैसे अधिक स्पष्ट है। यह अतिरेक या अस्पष्टता को जोड़ता है: क्या "ऑल" का अर्थ "इन 3 का सेट" या "इस वातावरण में सब कुछ" है? यदि मैं एक नया मूल्य जोड़ता हूं, तो क्या मुझे इसे भी जोड़ना चाहिए? अगर मैं देखूं कि किसी और ने सभी के लिए एक नया मूल्य नहीं जोड़ा है, तो क्या यह जानबूझकर है? ~ 0 स्पष्ट है।
केन

16
एक तरफ व्यक्तिगत पसंद, अगर ओपी का अर्थ ओपी के लिए उतना ही स्पष्ट था जितना कि आप और मैं, तो उसने इस सवाल को पहले स्थान पर नहीं रखा होगा। मुझे यकीन नहीं है कि एक दृष्टिकोण की स्पष्टता के बारे में क्या कहता है बनाम।
शॉन ब्राइट

9
चूँकि कुछ प्रोग्रामर जो C # का उपयोग करते हैं, उन्हें अभी तक पता नहीं है कि << का क्या मतलब है, क्या हमें अधिक स्पष्टता के लिए, उसके आसपास भी कोड करना चाहिए? मुझे नहीं लगता।
कर्ट कोल्लर

4
@Paul, वो दीवाना है। चलो का उपयोग बंद करो; अंग्रेजी में क्योंकि बहुत से लोग इसके उपयोग को नहीं समझते हैं। या वे सभी शब्द जो वे नहीं जानते। वाह, ऑपरेटरों का एक छोटा सा सेट, और हमें अपने कोड को उन लोगों के लिए गूंगा करना चाहिए जो नहीं जानते कि बिट्स क्या हैं और उन्हें कैसे हेरफेर करना है?
कर्ट कोल्लर

22
public enum PurchaseMethod
{   
    All = ~0, // all bits of All are 1. the ~ operator just inverts bits
    None =  0,
    Cash =  1,
    Check =  2,
    CreditCard =  4
}

सी # में दो पूरक के कारण ~0 == -1, वह संख्या जहां सभी बिट्स द्विआधारी प्रतिनिधित्व में 1 हैं।


ऐसा लगता है कि वे भुगतान विधि के लिए एक सा झंडा बना रहे हैं: 000 = कोई नहीं; 001 = नकद; 010 = चेक; 100 = क्रेडिट कार्ड; 111 = ऑल
डिलि-ओ

यह दो का पूरक नहीं है, यह सभी बिट्स को उल्टा करता है और एक को जोड़ता है, ताकि दोनों का 0 का पूरक अभी भी 0. है। ~ ~ 0 बस सभी बिट्स या किसी के पूरक को निष्क्रिय करता है।
Beardo

नहीं, दो के पूरक केवल सभी बिट्स को निष्क्रिय कर रहे हैं।
विन्यासकर्ता

2
@configurator - यह सही नहीं है। पूरक हैं बिट्स का एक सरल उलटा है।
डेव मार्कले

सी # नकारात्मक मूल्यों का प्रतिनिधित्व करने के लिए दो पूरक का उपयोग करता है। बेशक ~ दो पूरक नहीं है, लेकिन बस सभी बिट्स को निष्क्रिय कर देता है। मुझे यकीन नहीं है कि आपको वह कहाँ से मिला है, बेयर्डो
जोहान्स शहाब -

17

इसकी तुलना में बेहतर है

All = Cash | Check | CreditCard

समाधान, क्योंकि यदि आप बाद में कोई अन्य विधि जोड़ते हैं, तो कहें:

PayPal = 8 ,

आपको पहले से ही टिल्ड-ऑल के साथ किया जाएगा, लेकिन ऑल-लाइन को दूसरे के साथ बदलना होगा। इसलिए बाद में इसकी त्रुटि कम हो गई।

सादर


यह बेहतर है यदि आप यह भी कहते हैं कि यह कम त्रुटि वाला क्यों है। जैसे: यदि आप किसी डेटाबेस / बाइनरी फाइल में वैल्यू स्टोर करते हैं और फिर एन्यूमरेशन में एक और झंडा जोड़ते हैं, तो इसे 'ऑल' में शामिल किया जाएगा, जिसका अर्थ है कि 'ऑल' हमेशा सभी का अर्थ होगा, और न कि केवल तब तक झंडे वही हैं :)।
एदिकापी

11

बस एक साइड नोट, जब आप उपयोग करें

All = Cash | Check | CreditCard

आपके पास अतिरिक्त लाभ है जो किसी अन्य मूल्य (-1) का Cash | Check | CreditCardमूल्यांकन करेगा Allऔर नहीं करेगा जो सभी मानों के होते हुए भी सभी के लिए समान नहीं है। उदाहरण के लिए, यदि आप यूआई में तीन चेक बॉक्स का उपयोग करते हैं

[] Cash
[] Check
[] CreditCard

और उनके मानों को योग करें, और उपयोगकर्ता उन सभी का चयन करता है, Allजिसके परिणामस्वरूप आप परिणाम देखेंगे ।


इसलिए आप myEnum.HasFlag()इसके बजाय का उपयोग करते हैं: D
Pyritie

@Pyritie: आपकी टिप्पणी का मेरे द्वारा कही गई बातों से कोई लेना-देना नहीं है।
विन्यासकर्ता

जैसे ... यदि आपने "0" का उपयोग "ऑल" के लिए किया, तो आप कुछ ऐसा कर सकते हैं All.HasFlag(Cash | Check | CreditCard)और यह सच हो जाएगा। ==हमेशा 0 के साथ काम नहीं करता है क्योंकि एक समाधान होगा ।
११:१३ बजे पीरिटाई

ओह, मैं इस बारे में बात कर रहा था कि आप डिबगर में क्या देख रहे हैं और ToStringउपयोग करने के बारे में नहीं == All
विन्यासकर्ता

9

दूसरों के लिए, जिन्होंने इस प्रश्न को प्रकाशित किया, मेरे पास ~साझा करने के लिए एक त्वरित उदाहरण है। पेंट विधि के कार्यान्वयन से निम्नलिखित स्निपेट, जैसा कि इस मोनो प्रलेखन में विस्तृत है , ~बहुत प्रभाव का उपयोग करता है:

PaintCells (clipBounds, 
    DataGridViewPaintParts.All & ~DataGridViewPaintParts.SelectionBackground);

~ऑपरेटर के बिना , कोड शायद कुछ इस तरह दिखाई देगा:

PaintCells (clipBounds, DataGridViewPaintParts.Background 
    | DataGridViewPaintParts.Border
    | DataGridViewPaintParts.ContentBackground
    | DataGridViewPaintParts.ContentForeground
    | DataGridViewPaintParts.ErrorIcon
    | DataGridViewPaintParts.Focus);

... क्योंकि गणना इस तरह दिखता है:

public enum DataGridViewPaintParts
{
    None = 0,
    Background = 1,
    Border = 2,
    ContentBackground = 4,
    ContentForeground = 8,
    ErrorIcon = 16,
    Focus = 32,
    SelectionBackground = 64,
    All = 127 // which is equal to Background | Border | ... | Focus
}

शॉन ब्राइट के जवाब में इस एनम की समानता पर ध्यान दें?

मुझे लगता है कि मेरे लिए सबसे महत्वपूर्ण बात यह है कि ~एक एनम में एक ही ऑपरेटर है क्योंकि यह कोड की एक सामान्य लाइन में है।


अपने दूसरे कोड ब्लॉक में नहीं करना चाहिए &रों हो |रों?
क्लिक करें

@ क्लिक करें, पकड़ के लिए धन्यवाद। दूसरा कोड ब्लॉक वास्तव में अब समझ में आता है।
माइक

5

यह एक पूरक ऑपरेटर है, यहाँ एक लेख है जिसे मैं अक्सर बिटवाइज़ ऑपरेटरों के लिए संदर्भित करता हूं

http://www.blackwasp.co.uk/CSharpLogicalBitwiseOps.aspx

इसके अलावा msdn अपने enums लेख में इसका उपयोग करता है जो दर्शाता है कि यह बेहतर उपयोग करता है

http://msdn.microsoft.com/en-us/library/cc138362.aspx


1

वैकल्पिक रूप से मैं व्यक्तिगत रूप से उपयोग करता हूं, जो @ सीन ब्राइट के उत्तर की तुलना में एक ही काम करता है, लेकिन मुझे बेहतर लगता है, क्या यह एक है:

[Flags]
public enum PurchaseMethod
{
    None = 0,
    Cash = 1,
    Check = 2,
    CreditCard = 4,
    PayPal = 8,
    BitCoin = 16,
    All = Cash + Check + CreditCard + PayPal + BitCoin
}

ध्यान दें कि उन संख्याओं की द्विआधारी प्रकृति, जो दो की सभी शक्तियां हैं, निम्नलिखित दावे को सच बनाती हैं (a + b + c) == (a | b | c):। और IMHO, +बेहतर दिखता है।


1

मैंने ~ के साथ कुछ प्रयोग किया है और पाया है कि इसमें नुकसान हो सकता है। LINQPad के लिए इस स्निपेट पर विचार करें जो दर्शाता है कि सभी मानों को एक साथ व्यवहार नहीं किया जाता है जब सभी मान एक साथ ored होते हैं।

void Main()
{
    StatusFilterEnum x = StatusFilterEnum.Standard | StatusFilterEnum.Saved;
    bool isAll = (x & StatusFilterEnum.All) == StatusFilterEnum.All;
    //isAll is false but the naive user would expect true
    isAll.Dump();
}
[Flags]
public enum StatusFilterEnum {
      Standard =0,
      Saved =1,   
      All = ~0 
}

मानक को 0 मान नहीं मिलना चाहिए, लेकिन
0.10

0

बस जोड़ना चाहते हैं, यदि आप [झंडे] एनम का उपयोग करते हैं, तो बिटवाइज़ लेफ्ट शिफ्ट ऑपरेटर का उपयोग करना अधिक सुविधाजनक हो सकता है, जैसे:

[Flags]
enum SampleEnum
{
    None   = 0,      // 0
    First  = 1 << 0, // 1b    = 1d
    Second = 1 << 1, // 10b   = 2d
    Third  = 1 << 2, // 100b  = 4d
    Fourth = 1 << 3, // 1000b = 8d
    All    = ~0      // 11111111b
}

यह सवाल का जवाब बिल्कुल नहीं है।
सेरी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.