Catatan kecil: enum bitwise dalam C # harus mendapatkan atribut [Bendera] di atasnya.
Nyerguds
@Nyerguds, dapatkah Anda menjelaskan mengapa itu harus mendapatkan atribut?
ethane
Ini memberikan dukungan IntelliSense yang lebih baik saat debugging, karena ia mengakui nilai enum yang tidak diketahui sebagai kombinasi dari nilai yang ada.
Nyerguds
1
Ini juga memberikan nilai yang lebih bermakna .ToString(). misal RED, BLUE, YELLOWdaripada 22.
Sinjai
Jawaban:
331
Anda harus melakukannya &dengan ~(pelengkap) dari 'BIRU'.
Operator komplemen pada dasarnya membalikkan atau 'membalik' semua bit untuk tipe data yang diberikan. Dengan demikian, jika Anda menggunakan ANDoperator ( &) dengan beberapa nilai (sebut saja nilai itu 'X') dan komplemen dari satu atau lebih bit yang ditetapkan (sebut saja bit Qdan komplemennya ~Q), pernyataan X & ~Qmenghapus semua bit yang ditetapkan dalam Qdari Xdan mengembalikan hasilnya.
Jadi untuk menghapus atau menghapus BLUEbit, Anda menggunakan pernyataan berikut:
colorsWithoutBlue = colors &~Blah.BLUE
colors &=~Blah.BLUE // This one removes the bit from 'colors' itself
Anda juga dapat menentukan beberapa bit untuk dihapus, sebagai berikut:
colorsWithoutBlueOrRed = colors &~(Blah.BLUE |Blah.RED)
colors &=~(Blah.BLUE |Blah.RED)// This one removes both bits from 'colors' itself
atau secara bergantian ...
colorsWithoutBlueOrRed = colors &~Blah.BLUE &~Blah.RED
colors &=~Blah.BLUE &~Blah.RED // This one removes both bits from 'colors' itself
jadi jika saya ingin menghapus lebih banyak saya hanya akan melakukan: & = ~ Blah.BLUE & ~ Blah.Green?
Blankman
11
Lebih baikcolors &= ~( Blah.BLUE | Blah.GREEN );
par
2
betapa tidak biasa, saya hanya berpikir bagaimana melakukan ini lagi sekitar 5 hari yang lalu :) Pertanyaan ini diperbarui di kotak masuk dan voila saya!
Blankman
Jawaban yang bagus Saya pikir maksud Anda "& =" tidak "= &" dalam sampel kode Anda;)
Dave Jellison
48
Jawaban lainnya benar, tetapi untuk secara khusus menghapus biru dari yang di atas Anda akan menulis:
Kupikir ini mungkin berguna untuk orang lain yang tersandung di sini seperti aku.
Berhati-hatilah bagaimana Anda menangani nilai enum apa pun yang mungkin Anda tetapkan untuk memiliki nilai == 0 (kadang-kadang bisa bermanfaat untuk memiliki keadaan Tidak Dikenal atau Menganggur untuk enum). Ini menyebabkan masalah ketika mengandalkan operasi manipulasi bit ini.
Juga ketika Anda memiliki nilai enum yang merupakan kombinasi dari kekuatan lain dari 2 nilai, misalnya
publicenumColour{None=0,// default value
RED =2,
BLUE =4,
GREEN =8,
YELLOW =16,Orange=18// Combined value of RED and YELLOW}
Dalam kasus ini, metode ekstensi seperti ini mungkin berguna:
publicstaticColourUnSet(thisColour states,Colour state){if((int)states ==0)return states;if(states == state)returnColour.None;return states &~state;}
Dan juga metode IsSet ekuivalen yang menangani nilai-nilai gabungan (meskipun sedikit cara hacky)
publicstaticboolIsSet(thisColour states,Colour state){// By default if not OR'dif(states == state)returntrue;// Combined: One or more bits need to be setif( state ==Colour.Orange)return0!=(int)(states & state);// Non-combined: all bits need to be setreturn(states & state)== state;}
Sepertinya saya bahwa solusi yang lebih sederhana adalah menghindari menggunakan 0 sebagai flag. Saya biasanya mengatur flag enums seperti ini . Saya tidak melihat bagaimana Anda mendapat manfaat dari menetapkan negara dengan nilai 0. Setelah semua, intinya adalah bahwa Anda dapat menyibukkan diri dengan nama ramah-programmer ( Red, Blue, Green) daripada nilai-nilai yang mendasarinya, ya?
Sinjai
Memiliki noneatau unknownatau unsetentri dengan nilai == 0 dalam banyak kasus adalah hal yang baik karena Anda tidak selalu dapat berasumsi bahwa nilai tertentu adalah set default, misalnya jika Anda hanya memiliki Merah, Biru dan Hijau Anda akan memiliki Merah sebagai nilai default (mis. nilai yang dimiliki enum saat dibuat atau pengguna belum memodifikasinya?)
Sverrir Sigmundarson
Tidak bisakah Anda memiliki Unset = 1 dan gunakan 1, 2, 4, 8sebagai nilai Anda? Jika Anda membutuhkan nilai default, itulah gunanya konstruktor default, bukan? Saya suka menjaga hal-hal sejelas mungkin demi keterbacaan, dan mengandalkan enum ke default ke default(int)( 0) ketika tidak diberi nilai, meskipun informasi mungkin diketahui oleh pengembang mana pun, bagaimanapun juga terlalu licik untuk seleraku. Sunting: Oh, tunggu, apakah membuat Unset = 0 mencegah sesuatu menjadi tidak ada Unset | Blue?
Sinjai
Anda berada di jalur yang benar di Sinjai edit, menjaga nilai yang tidak disetel == 0 benar-benar memecahkan beberapa masalah. Satu menjadi apa yang Anda sebutkan dan satu lainnya adalah jika Anda tidak menyetel semua nilai enum maka Anda tidak memerlukan kasus khusus untuk "Tidak disetel" jika disetel ke nol. (mis. jika Anda Red & ~Redkemudian berakhir dengan nol maka Anda harus memiliki kode untuk memeriksa kasus ini dan secara eksplisit menetapkan Unsetnilainya)
Sverrir Sigmundarson
Kena kau. Apakah Anda sering berhadapan dengan bendera yang tidak disetel?
Sinjai
2
Bagaimana dengan xor (^)?
Mengingat bahwa FLAG yang Anda coba hapus ada di sana, itu akan berfungsi .. jika tidak, Anda harus menggunakan &.
publicenumColour{None=0,// default value
RED =2,
BLUE =4,
GREEN =8,
YELLOW =16,Orange=18// Combined value of RED and YELLOW}
colors =(colors ^Colour.RED)& colors;
Untuk menyederhanakan flag enum dan membuatnya mungkin lebih baik untuk dibaca dengan menghindari kelipatan, kita dapat menggunakan bit shifting. (Dari artikel bagus Mengakhiri Debat Hebat di Bendera Enum )
[FLAG]EnumBlah{
RED =1,
BLUE =1<<1,
GREEN =1<<2,
YELLOW =1<<3}
.ToString()
. misalRED, BLUE, YELLOW
daripada22
.Jawaban:
Anda harus melakukannya
&
dengan~
(pelengkap) dari 'BIRU'.Operator komplemen pada dasarnya membalikkan atau 'membalik' semua bit untuk tipe data yang diberikan. Dengan demikian, jika Anda menggunakan
AND
operator (&
) dengan beberapa nilai (sebut saja nilai itu 'X') dan komplemen dari satu atau lebih bit yang ditetapkan (sebut saja bitQ
dan komplemennya~Q
), pernyataanX & ~Q
menghapus semua bit yang ditetapkan dalamQ
dariX
dan mengembalikan hasilnya.Jadi untuk menghapus atau menghapus
BLUE
bit, Anda menggunakan pernyataan berikut:Anda juga dapat menentukan beberapa bit untuk dihapus, sebagai berikut:
atau secara bergantian ...
Jadi untuk meringkas:
X | Q
set bitQ
X & ~Q
membersihkan bitQ
~X
membalik / membalikkan semua bitX
sumber
colors &= ~( Blah.BLUE | Blah.GREEN );
Jawaban lainnya benar, tetapi untuk secara khusus menghapus biru dari yang di atas Anda akan menulis:
sumber
And not
Itu...............................sumber
Kupikir ini mungkin berguna untuk orang lain yang tersandung di sini seperti aku.
Berhati-hatilah bagaimana Anda menangani nilai enum apa pun yang mungkin Anda tetapkan untuk memiliki nilai == 0 (kadang-kadang bisa bermanfaat untuk memiliki keadaan Tidak Dikenal atau Menganggur untuk enum). Ini menyebabkan masalah ketika mengandalkan operasi manipulasi bit ini.
Juga ketika Anda memiliki nilai enum yang merupakan kombinasi dari kekuatan lain dari 2 nilai, misalnya
Dalam kasus ini, metode ekstensi seperti ini mungkin berguna:
Dan juga metode IsSet ekuivalen yang menangani nilai-nilai gabungan (meskipun sedikit cara hacky)
sumber
Red, Blue, Green
) daripada nilai-nilai yang mendasarinya, ya?none
atauunknown
atauunset
entri dengan nilai == 0 dalam banyak kasus adalah hal yang baik karena Anda tidak selalu dapat berasumsi bahwa nilai tertentu adalah set default, misalnya jika Anda hanya memiliki Merah, Biru dan Hijau Anda akan memiliki Merah sebagai nilai default (mis. nilai yang dimiliki enum saat dibuat atau pengguna belum memodifikasinya?)1, 2, 4, 8
sebagai nilai Anda? Jika Anda membutuhkan nilai default, itulah gunanya konstruktor default, bukan? Saya suka menjaga hal-hal sejelas mungkin demi keterbacaan, dan mengandalkan enum ke default kedefault(int)
(0
) ketika tidak diberi nilai, meskipun informasi mungkin diketahui oleh pengembang mana pun, bagaimanapun juga terlalu licik untuk seleraku. Sunting: Oh, tunggu, apakah membuat Unset = 0 mencegah sesuatu menjadi tidak adaUnset | Blue
?Red & ~Red
kemudian berakhir dengan nol maka Anda harus memiliki kode untuk memeriksa kasus ini dan secara eksplisit menetapkanUnset
nilainya)Bagaimana dengan xor (^)?
Mengingat bahwa FLAG yang Anda coba hapus ada di sana, itu akan berfungsi .. jika tidak, Anda harus menggunakan &.
sumber
Untuk menyederhanakan flag enum dan membuatnya mungkin lebih baik untuk dibaca dengan menghindari kelipatan, kita dapat menggunakan bit shifting. (Dari artikel bagus Mengakhiri Debat Hebat di Bendera Enum )
dan juga untuk menghapus semua bit
sumber
Anda bisa menggunakan ini:
sumber