এনাম অনুমতিগুলির প্রায়শই 0, 1, 2, 4 মান থাকে কেন?


159

কেন লোকেরা সর্বদা এনাম মানগুলি ব্যবহার করে 0, 1, 2, 4, 8এবং পছন্দ করে না 0, 1, 2, 3, 4?

বিট অপারেশন ইত্যাদির সাথে এটির কি কিছু করার আছে?

এটি কীভাবে সঠিকভাবে ব্যবহৃত হয় তার জন্য আমি একটি ছোট নমুনার স্নিপেটের সত্যই প্রশংসা করব :)

[Flags]
public enum Permissions
{
    None   = 0,
    Read   = 1,
    Write  = 2,
    Delete = 4
}


25
আমি দুপ ভোটে একমত নই
zzzzBov

ইউনিক্সের অনুমতি সেট করার উপায়টিও একই যুক্তির উপর ভিত্তি করে।
রুডি

3
@ পাসকল: আপনি বিটওয়্যার ওআর (এবং বিটওয়াইস এন্ড ) সম্পর্কে পড়তে সহায়ক বলে মনে করতে পারেন , যা |(এবং &) প্রতিনিধিত্ব করে। বিভিন্ন উত্তর ধরে নেয় আপনি এটির সাথে পরিচিত।
ব্রায়ান

2
@ আইডিএপ্টার আমি দেখতে পাচ্ছি আপনি কেন এমনটি ভাবছেন, কারণ উভয়ের উত্তর একই, তবে আমার মনে হয় প্রশ্নগুলি আলাদা। অন্যান্য প্রশ্নটি কেবল # # তে ফ্ল্যাগগুলির বৈশিষ্ট্যের উদাহরণ বা ব্যাখ্যা চেয়েছে। এই প্রশ্নটি বিট পতাকাগুলির ধারণা এবং তাদের পিছনে মূল বিষয়গুলি সম্পর্কে বলে মনে হচ্ছে।
জেরেমি এস

উত্তর:


268

কারণ তারা দু'জনের শক্তি এবং আমি এটি করতে পারি:

var permissions = Permissions.Read | Permissions.Write;

এবং সম্ভবত পরে ...

if( (permissions & Permissions.Write) == Permissions.Write )
{
    // we have write access
}

এটি একটি বিট ক্ষেত্র, যেখানে প্রতিটি সেট বিট কিছু অনুমতির সাথে মিলে যায় (বা বর্ণিত মানটি যা যুক্তিযুক্ত তার সাথে মিল রাখে)। যদি এগুলি সংজ্ঞায়িত করা হয় তবে 1, 2, 3, ...আপনি এই ফ্যাশনে বিটওয়াইজ অপারেটরগুলি ব্যবহার করতে পারবেন না এবং অর্থবহ ফলাফল পাবেন। আরও গভীরভাবে আবিষ্কার করতে ...

Permissions.Read   == 1 == 00000001
Permissions.Write  == 2 == 00000010
Permissions.Delete == 4 == 00000100

এখানে একটি নিদর্শন লক্ষ্য করুন? এখন যদি আমরা আমার মূল উদাহরণটি গ্রহণ করি, যেমন,

var permissions = Permissions.Read | Permissions.Write;

তারপর ...

permissions == 00000011

দেখা? উভয় Readএবং Writeবিট সেট করা আছে, এবং আমি পরীক্ষা করতে পারবেন যে স্বাধীনভাবে (এছাড়াও যে বিজ্ঞপ্তি Deleteবিট হয় না সেট এবং সেইজন্য এই মান মোছার জন্য আপনাকে অনুমতি বহন করে না)।

এটি বিটগুলির একক ক্ষেত্রে একাধিক পতাকা সংরক্ষণ করতে দেয়।


2
@ ম্যালকম: এটি করে; myEnum.IsSet। আমি মতামত যে এটি একটি সম্পূর্ণ অকেজো বিমূর্ততা এবং শুধুমাত্র টাইপিং কেটে ফেলতে কাজ করে তবে মেহ
এড এস

1
উত্তম উত্তর, তবে ফ্ল্যাগের বৈশিষ্ট্যটি কেন প্রয়োগ করা হয় তা আপনার উল্লেখ করা উচিত এবং যখন আপনি কিছু এনামগুলিতেও পতাকা প্রয়োগ করতে চান না।
অ্যান্ডি

3
@ অ্যান্ডি: আসলে, Flagsগুণটি আপনাকে 'প্রিন্টিং প্রিন্টিং' আইরিক দেওয়ার চেয়ে কিছুটা কম করে। বৈশিষ্ট্যের উপস্থিতি নির্বিশেষে আপনি পতাকা হিসাবে একটি অঙ্কিত মান ব্যবহার করতে পারেন।
এড এস

3
@ বিশদভাবে: কারণ যদি সি # তে বিবৃতিগুলির জন্য বুলিয়ান অভিব্যক্তি প্রয়োজন। 0না false; falseহয় false। আপনি তবে লিখতে পারেন if((permissions & Permissions.Write) > 0)
এড এস

2
'ছদ্মবেশী' পরিবর্তে (permissions & Permissions.Write) == Permissions.Writeআপনি এখন ব্যবহার করতে পারেনenum.HasFlag()
লুই কোটম্যান

147

এটি এখনও অন্য উত্তরগুলি থেকে পরিষ্কার না হলে এটি সম্পর্কে এইভাবে চিন্তা করুন:

[Flags] 
public enum Permissions 
{   
   None = 0,   
   Read = 1,     
   Write = 2,   
   Delete = 4 
} 

লেখার জন্য কেবল একটি ছোট্ট উপায়:

public enum Permissions 
{   
    DeleteNoWriteNoReadNo = 0,   // None
    DeleteNoWriteNoReadYes = 1,  // Read
    DeleteNoWriteYesReadNo = 2,  // Write
    DeleteNoWriteYesReadYes = 3, // Read + Write
    DeleteYesWriteNoReadNo = 4,   // Delete
    DeleteYesWriteNoReadYes = 5,  // Read + Delete
    DeleteYesWriteYesReadNo = 6,  // Write + Delete
    DeleteYesWriteYesReadYes = 7, // Read + Write + Delete
} 

আটটি সম্ভাবনা রয়েছে তবে আপনি কেবল চার সদস্যের সংমিশ্রণ হিসাবে তাদের প্রতিনিধিত্ব করতে পারেন। যদি ষোলটি সম্ভাবনা থাকে তবে আপনি কেবল পাঁচ সদস্যের সংমিশ্রণ হিসাবে তাদের প্রতিনিধিত্ব করতে পারেন। যদি চার বিলিয়ন সম্ভাবনা থাকে তবে আপনি কেবলমাত্র 33 সদস্যের সংমিশ্রণ হিসাবে তাদের প্রতিনিধিত্ব করতে পারেন! এনামে চার বিলিয়ন আইটেমের নাম রাখার চেষ্টা করার চেয়ে মাত্র ৩৩ জন সদস্যের প্রত্যেকের (শূন্য ব্যতিত) দু'জনের শক্তি থাকা স্পষ্টতই ভাল।


32
enumচার বিলিয়ন সদস্য বিশিষ্টের মানসিক চিত্রের জন্য +1 । এবং দুঃখের বিষয়টি হ'ল সম্ভবতঃ কেউ কেউ চেষ্টা করেছে।
ড্যানিয়েল প্রাইডেন

23
@ ড্যানিয়েলপ্রাইডেন ডেইলি ডাব্লুটিএফ-র একজন পাঠক হিসাবে, আমি এটি বিশ্বাস করব।
ফ্লফি

1
2 ^ 33 = ~ 8.6 বিলিয়ন। 4 বিলিয়ন বিভিন্ন মানের জন্য আপনার কেবল 32 বিট দরকার।
সিভিএন

5
@ মাইকেলকিজারলিং 33 টির মধ্যে একটি 0 টি ডিফল্ট
র‌্যাচেট ফ্রিক

@ মাইকেলকার্জলিং: ন্যায্য কথা বলতে গেলে এখানে কেবলমাত্র 32 জন সদস্য রয়েছেন যা 2 এর শক্তি, যেহেতু 0 দুটির শক্তি নয়। সুতরাং "৩৩ জন সদস্য, প্রত্যেকে দু'জনের একটি শক্তি" যথাযথভাবে সঠিক নয় (যদি না আপনি 2 ** -infinityদু'জনের শক্তি হিসাবে গণনা করেন)।
ব্রায়ান

36

কারণ এই মানগুলি বাইনারিটিতে অনন্য বিট অবস্থানের প্রতিনিধিত্ব করে:

1 == binary 00000001
2 == binary 00000010
4 == binary 00000100

ইত্যাদি

1 | 2 == binary 00000011

সম্পাদনা করুন:

3 == binary 00000011

বাইনারি 3 টি একই স্থান এবং দুই স্থান উভয়ই 1 এর মান দ্বারা প্রতিনিধিত্ব করে। এটি আসলে মান হিসাবে একই 1 | 2। সুতরাং যখন আপনি কোনও রাজ্যের প্রতিনিধিত্ব করার জন্য বাইনারি জায়গাগুলি পতাকা হিসাবে ব্যবহার করার চেষ্টা করছেন তখন 3 সাধারণত অর্থবহ হয় না (যদি না কোনও যৌক্তিক মান না থাকে যা আসলে দুটির সংমিশ্রণ হয়)

আরও স্পষ্টতার জন্য, আপনি নীচের হিসাবে আপনার উদাহরণ এনাম প্রসারিত করতে পারেন:

[Flags]
public Enum Permissions
{
  None = 0,   // Binary 0000000
  Read = 1,   // Binary 0000001
  Write = 2,  // Binary 0000010
  Delete = 4, // Binary 0000100
  All = 7,    // Binary 0000111
}

অতএব আমি আছে Permissions.Allআমিও পরোক্ষভাবে আছে Permissions.Read, Permissions.WriteএবংPermissions.Delete


এবং 2 | 3 এ সমস্যা কি?
পাস্কল

1
@Pascal: যেহেতু 3হয় 11বাইনারি, অর্থাৎ, এটি একটি একক সেট বিট ম্যাপ নেই তাই আপনি একটি অর্থপূর্ণ মান একটি অবাধ অবস্থানে 1 বিট ম্যাপ ক্ষমতা হারান।
এড এস

8
@ পাসল আরেকটি উপায় রাখুন 2|3 == 1|3 == 1|2 == 3,। তাই আপনি যদি বাইনারি সঙ্গে একটি মূল্য আছে 00000011, এবং আপনার পতাকার মান অন্তর্ভুক্ত 1, 2এবং 3, তাহলে আপনি যদি যে মান প্রতিনিধিত্ব করে জানতাম না 1 and 3, 2 and 3, 1 and 2বা only 3। এটি এটি অনেক কম দরকারী করে তোলে।
ysavit

10
[Flags]
public Enum Permissions
{
    None   =    0; //0000000
    Read   =    1; //0000001
    Write  = 1<<1; //0000010
    Delete = 1<<2; //0000100
    Blah1  = 1<<3; //0001000
    Blah2  = 1<<4; //0010000
}

আমি মনে করি এরকম লেখা বোঝা এবং পড়া সহজ এবং আপনার এটি গণনার দরকার নেই।


5

এগুলি বিট পতাকাগুলি উপস্থাপন করতে ব্যবহৃত হয় যা এনাম মানগুলির সংমিশ্রণকে অনুমতি দেয়। আমি মনে করি আপনি যদি হেক্স নোটেশনে মান লিখেন তবে এটি আরও স্পষ্ট

[Flags]
public Enum Permissions
{
  None =  0x00,
  Read =  0x01,
  Write = 0x02,
  Delete= 0x04,
  Blah1 = 0x08,
  Blah2 = 0x10
}

4
@ প্যাস্কাল: সম্ভবত সময়ে সময়ে এটি আপনার পক্ষে আরও পঠনযোগ্য, তবে আপনি হেক্সে বাইট দেখার অভিজ্ঞতা অর্জনের পরে এটি দ্বিতীয় প্রকৃতিতে পরিণত হয়। এক বাইট মানচিত্রে হেক্স ম্যাপে দুটি অঙ্ক 8 টি বিটের মানচিত্রে (ভাল ... একটি বাইট সাধারণত 8 বিট যাইহোক হয় ... সর্বদা সত্য নয়, তবে এই উদাহরণের জন্য এটি জেনারালাইজ করা ঠিক আছে)।
এড এস

5
@ প্যাস্কল দ্রুত, আপনি 41943042 দিয়ে গুণ করলে আপনি কী পাবেন ? কীভাবে 0x400000? এর 0x800000চেয়ে সঠিক উত্তর হিসাবে এটি সনাক্ত করা অনেক সহজ 8388608এবং হেক্স মান টাইপ করার ক্ষেত্রে এটি ত্রুটি-প্রবণতাও কম।
ফুগ

6
যদি আপনি হেক্স ব্যবহার করেন তবে আপনার পতাকাগুলি সঠিকভাবে সেট করা থাকলে (যেমন, 2 এর শক্তি) যদি এটি এক নজরে বলা যায় তবে এটি অনেক সহজ। কি 0x10000দুই একটি ক্ষমতা? হ্যাঁ, এটি 1, 2, 4 বা 8 দিয়ে শুরু হয় এবং এর পরে 0 থাকে। আপনার মানসিকভাবে 0x10 থেকে 16 অনুবাদ করার দরকার নেই (যদিও এটি করার ফলে শেষ পর্যন্ত সম্ভবত দ্বিতীয় প্রকৃতি হয়ে উঠবে), কেবল এটি "2 এর শক্তি" হিসাবে ভাবেন।
ব্রায়ান

1
হেক্সে নোট করা আরও সহজ হওয়া সম্পর্কে আমি একেবারে জারেডের সাথে আছি। আপনি কেবল 1 2 4 8 এবং শিফট
বেভাচাকু

1
ব্যক্তিগতভাবে, আমি যেমন P_READ = 1 << 0, P_WRITE = 1 <, 1, P_RW = P_READ | P_WRITE ব্যবহার করতে পছন্দ করি। আমি নিশ্চিত নই যে এই ধরণের ধ্রুবক-ভাঁজ সি # তে কাজ করে তবে এটি সি / সি ++ (পাশাপাশি জাভা হিসাবেও আমার মনে হয়) ঠিক কাজ করে।
ফ্লাফি

1

এটি সত্যিই একটি মন্তব্য, তবে যেহেতু এটি ফর্ম্যাটিং সমর্থন করে না, তাই আমি কেবল পতাকা পদ্ধতিতে সেট করার জন্য আমি একটি পদ্ধতি অন্তর্ভুক্ত করতে চেয়েছিলাম:

[Flags]
public enum FlagTest
{
    None = 0,
    Read = 1,
    Write = Read * 2,
    Delete = Write * 2,
    ReadWrite = Read|Write
}

আপনি বর্ণানুক্রমিক ক্রমে আপনার পতাকা বজায় রাখতে চান এমন ক্ষেত্রে উন্নয়নের সময় আমি এই পদ্ধতির বিশেষত সহায়ক বলে মনে করি। যদি আপনি নির্ধারণ করেন যে আপনাকে একটি নতুন পতাকা মান যুক্ত করতে হবে, আপনি কেবল বর্ণানুক্রমিকভাবে এটি সন্নিবেশ করতে পারেন এবং আপনার কেবলমাত্র মানটি পরিবর্তন করতে হবে যা এটি এর আগে রয়েছে।

দ্রষ্টব্য, তবে একবার যে কোনও সমাধান সিস্টেমে কোনও সমাধান প্রকাশিত হয় (বিশেষত যদি এনামটি কোনও টাইট কাপলিং ব্যতীত কোনও ওয়েব সার্ভিসের মাধ্যমে প্রকাশ করা হয়), তবে এনামের মধ্যে বিদ্যমান মান পরিবর্তনের বিরুদ্ধে এটি অত্যন্ত পরামর্শ দেওয়া হয়।


1

লোটের এই এক ভাল উত্তর ... আমি শুধু বলবো .. যদি আপনি পছন্দ করেন না, বা সহজে উপলব্ধি করতে পারবে না কি <<সিনট্যাক্স প্রকাশ করার .. আমি ব্যক্তিগতভাবে একটি বিকল্প পছন্দ করা চেষ্টা করছে (এবং সাহস আমি বলি, সহজবোধ্য enum ঘোষণা শৈলী) ...

typedef NS_OPTIONS(NSUInteger, Align) {
    AlignLeft         = 00000001,
    AlignRight        = 00000010,
    AlignTop          = 00000100,
    AlignBottom       = 00001000,
    AlignTopLeft      = 00000101,
    AlignTopRight     = 00000110,
    AlignBottomLeft   = 00001001,
    AlignBottomRight  = 00001010
};

NSLog(@"%ld == %ld", AlignLeft | AlignBottom, AlignBottomLeft);

LOG 513 == 513

বুঝতে এত সহজ (আমার পক্ষে, কমপক্ষে)। এগুলি সীমাবদ্ধ করুন ... আপনি যে ফলাফলটি চান তা বর্ণনা করুন, ফলাফলটি আপনি চান ..

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.