Katakanlah saya memiliki yang berikut ini
int susan = 2; //0010
int bob = 4; //0100
int karen = 8; //1000
dan saya meneruskan 10 (8 + 2) sebagai parameter ke metode dan saya ingin memecahkan kode ini menjadi susan dan karen
Saya tahu bahwa 10 adalah 1010
tetapi bagaimana saya bisa melakukan logika untuk melihat apakah bit tertentu dicentang seperti pada
if (condition_for_karen) // How to quickly check whether effective karen bit is 1
Saat ini yang bisa saya pikirkan adalah memeriksa apakah nomor yang saya lulus adalah
14 // 1110
12 // 1100
10 // 1010
8 // 1000
Ketika saya memiliki jumlah bit aktual yang lebih besar dalam skenario dunia nyata saya, ini sepertinya tidak praktis, cara apa yang lebih baik menggunakan topeng untuk sekadar memeriksa apakah saya memenuhi syarat untuk sekedar karen?
Saya dapat memikirkan untuk menggeser ke kiri lalu ke belakang lalu menggeser ke kanan lalu kembali ke bagian yang jelas selain yang saya minati, tetapi ini juga tampak terlalu rumit.
Jawaban:
Cara tradisional untuk melakukannya adalah dengan menggunakan
Flags
atribut padaenum
:Kemudian Anda akan memeriksa nama tertentu sebagai berikut:
Kombinasi bitwise yang logis bisa jadi sulit untuk diingat, jadi saya membuat hidup saya lebih mudah dengan
FlagsHelper
kelas *:Ini akan memungkinkan saya untuk menulis ulang kode di atas sebagai:
Catatan Saya juga bisa menambahkan
Karen
ke set dengan melakukan ini:Dan saya bisa menghapus
Susan
dengan cara yang sama:* Sebagai Porges menunjukkan, setara dengan yang
IsSet
metode di atas sudah ada di NET 4.0:Enum.HasFlag
. NamunSet
,Unset
metode dan tampaknya tidak memiliki padanan; jadi saya masih akan mengatakan kelas ini memiliki beberapa manfaat.Catatan: Menggunakan enum hanyalah cara konvensional untuk mengatasi masalah ini. Anda benar-benar dapat menerjemahkan semua kode di atas untuk menggunakan int sebagai gantinya dan itu akan bekerja dengan baik.
sumber
(names & Names.Susan) == Names.Susan
, yang tidak memerlukan fileNone
.None
nilai untuk semua enum saya, karena saya merasa itu akhirnya menjadi nyaman dalam banyak skenario.var susanIsIncluded = names.HasFlag(Names.Susan);
Set
metode ini. Jadi, menurut saya metode pembantu setidaknya tidak sepenuhnya tidak berharga.)names.HasFlag(Names.Susan)
seperti(names & Names.Susan) == Names.Susan
itu tidak selalu seperti itu(names & Names.Susan) != Names.None
. Misalnya jika Anda akan memeriksa apakahnames.HasFlag(Names.none)
ataunames.HasFlag(Names.Susan|Names.Karen)
Bitwise 'and' akan menutupi semuanya kecuali bit yang "mewakili" Karen. Selama setiap orang diwakili oleh satu posisi bit, Anda dapat memeriksa beberapa orang dengan cara sederhana:
sumber
Saya telah menyertakan contoh di sini yang menunjukkan bagaimana Anda dapat menyimpan mask di kolom database sebagai int, dan bagaimana Anda akan mengembalikan mask nanti:
sumber
Untuk menggabungkan bitmask Anda ingin menggunakan bitwise- atau . Dalam kasus sepele di mana setiap nilai yang Anda gabungkan memiliki tepat 1 bit (seperti contoh Anda), itu setara dengan menambahkannya. Namun, jika Anda memiliki bit yang tumpang tindih, atau mereka menangani kasing dengan baik.
Untuk memecahkan kode bitmask Anda dan nilai Anda dengan mask, seperti ini:
sumber
Jalan mudah:
Untuk menyetel tanda, gunakan operator "atau" logika
|
:Dan untuk memeriksa apakah sebuah bendera disertakan, gunakan
HasFlag
:sumber
HasFlag()
dan the[Flags]
tidak tersedia di jawaban lain.Satu alasan lain yang sangat bagus untuk menggunakan bitmask vs individual bools adalah sebagai pengembang web, ketika mengintegrasikan satu situs web ke situs web lain, kita sering kali perlu mengirim parameter atau tanda di string kueri. Selama semua flag Anda adalah biner, akan lebih mudah menggunakan satu nilai sebagai bitmask daripada mengirim banyak nilai sebagai bools. Saya tahu ada cara lain untuk mengirim data (GET, POST, dll.), Tetapi parameter sederhana pada querystring seringkali cukup untuk item yang tidak sensitif. Cobalah untuk mengirim 128 nilai bool pada querystring untuk berkomunikasi dengan situs eksternal. Ini juga memberikan kemampuan tambahan untuk tidak memaksakan batasan pada querystring url di browser
sumber