Untuk kehidupan saya, saya tidak ingat bagaimana mengatur, menghapus, beralih atau menguji sedikit di bitfield. Entah saya tidak yakin atau saya mencampurnya karena saya jarang membutuhkan ini. Jadi "bit-cheat-sheet" akan menyenangkan untuk dimiliki.
Sebagai contoh:
flags = flags | FlagsEnum.Bit4; // Set bit 4.
atau
if ((flags & FlagsEnum.Bit4)) == FlagsEnum.Bit4) // Is there a less verbose way?
Bisakah Anda memberikan contoh dari semua operasi umum lainnya, lebih disukai dalam sintaks C # menggunakan enum [Bendera]?
Jawaban:
Saya melakukan beberapa pekerjaan pada ekstensi ini - Anda dapat menemukan kode di sini
Saya menulis beberapa metode ekstensi yang memperpanjang System.Enum yang sering saya gunakan ... Saya tidak mengklaim bahwa mereka antipeluru, tetapi mereka telah membantu ... Komentar dihapus ...
Kemudian mereka digunakan seperti berikut ini
sumber
HasFlag
metode baru padaEnum
membutuhkan tinju.Di .NET 4 Anda sekarang dapat menulis:
sumber
FlagsEnum
nama yang jelek. :)[Flags]
enum harus memiliki nama pluralised, sehingga namaFlagsEnum
memiliki bahkan masalah yang lebih serius daripada keburukan.Idiomnya adalah menggunakan operator bitwise atau-sama untuk mengatur bit:
Untuk menghapus sedikit, idiomnya adalah menggunakan bitwise dan dengan negasi:
Kadang-kadang Anda memiliki offset yang mengidentifikasi bit Anda, dan kemudian idiomnya adalah menggunakan ini dikombinasikan dengan shift kiri:
sumber
@Drew
Perhatikan bahwa kecuali dalam kasus yang paling sederhana, Enum.HasFlag membawa penalti performa yang berat dibandingkan dengan menuliskan kode secara manual. Pertimbangkan kode berikut:
Lebih dari 10 juta iterasi, metode ekstensi HasFlags mengambil 4793 ms kekalahan, dibandingkan dengan 27 ms untuk implementasi bitwise standar.
sumber
HasFlag
Metode melibatkan tinju / unboxing, yang menyumbang perbedaan ini. Tetapi biayanya sangat sepele (0,4 μs) sehingga kecuali Anda berada dalam lingkaran yang ketat, saya akan menerima panggilan deklaratif API yang lebih mudah dibaca (dan kurang memungkinkan buggy) setiap hari.Sayangnya, operasi flag enum bawaan NET. Cukup terbatas. Sebagian besar waktu pengguna dibiarkan mencari tahu logika operasi bitwise.
Dalam. NET 4, metode
HasFlag
ini ditambahkan keEnum
yang membantu menyederhanakan kode pengguna tetapi sayangnya ada banyak masalah dengannya.HasFlag
bukan tipe-aman karena menerima semua jenis argumen nilai enum, bukan hanya tipe enum yang diberikan.HasFlag
tidak jelas apakah memeriksa apakah nilai memiliki semua atau salah satu flag yang disediakan oleh argumen nilai enum. Semua itu omong-omong.HasFlag
agak lambat karena membutuhkan tinju yang menyebabkan alokasi dan dengan demikian lebih banyak pengumpulan sampah.Sebagian karena .NET dukungan terbatas untuk flag enums saya menulis perpustakaan OSS Enums.NET yang membahas masing-masing masalah ini dan membuat berurusan dengan flag enums lebih mudah.
Di bawah ini adalah beberapa operasi yang disediakan beserta implementasinya yang setara hanya dengan menggunakan .NET framework.
Gabungkan Bendera
.BERSIH
flags | otherFlags
Enums.NET
flags.CombineFlags(otherFlags)
Hapus Bendera
.BERSIH
flags & ~otherFlags
Enums.NET
flags.RemoveFlags(otherFlags)
Bendera umum
.BERSIH
flags & otherFlags
Enums.NET
flags.CommonFlags(otherFlags)
Toggle Flags
.BERSIH
flags ^ otherFlags
Enums.NET
flags.ToggleFlags(otherFlags)
Memiliki Semua Bendera
.NET
(flags & otherFlags) == otherFlags
atauflags.HasFlag(otherFlags)
Enums.NET
flags.HasAllFlags(otherFlags)
Memiliki Bendera Apa Pun
.BERSIH
(flags & otherFlags) != 0
Enums.NET
flags.HasAnyFlags(otherFlags)
Dapatkan Bendera
.BERSIH
Enums.NET
flags.GetFlags()
Saya mencoba untuk mendapatkan perbaikan ini dimasukkan ke dalam. NET Core dan mungkin akhirnya .NET Framework. Anda dapat memeriksa proposal saya di sini .
sumber
Sintaks C ++, dengan asumsi bit 0 adalah LSB, dengan asumsi flag tidak ditandai:
Periksa apakah Set:
Periksa apakah tidak disetel:
Set:
Bersih:
Beralih:
sumber
Untuk kinerja terbaik dan nol sampah, gunakan ini:
sumber
Untuk menguji sedikit Anda akan melakukan hal berikut: (dengan asumsi bendera adalah angka 32 bit)
Bit Uji:
(Jika bit 4 disetel maka itu benar) Toggle Back (1 - 0 atau 0 - 1): Setel Ulang Bit 4 ke Nol:sumber
~0x08
alih-alih0xFFFFFFF7
... (topeng sebenarnya untuk 0x8)Ini terinspirasi oleh menggunakan Sets sebagai pengindeks di Delphi, jalan kembali ketika:
sumber
Operasi C ++ adalah: & | ^ ~ (untuk dan, atau, xor dan bukan operasi bitwise). Yang juga menarik adalah >> dan <<, yang merupakan operasi bitshift.
Jadi, untuk menguji bit yang diatur dalam sebuah flag, Anda akan menggunakan: if (flags & 8) // tes bit 4 telah ditetapkan
sumber