ฉันมี Enum เช่น:
public enum Blah
{
RED = 2,
BLUE = 4,
GREEN = 8,
YELLOW = 16
}
Blah colors = Blah.RED | Blah.BLUE | Blah.YELLOW;
ฉันจะลบสีน้ำเงินออกจากสีตัวแปรได้อย่างไร
.ToString()
ค่า เช่นมากกว่าRED, BLUE, YELLOW
22
ฉันมี Enum เช่น:
public enum Blah
{
RED = 2,
BLUE = 4,
GREEN = 8,
YELLOW = 16
}
Blah colors = Blah.RED | Blah.BLUE | Blah.YELLOW;
ฉันจะลบสีน้ำเงินออกจากสีตัวแปรได้อย่างไร
.ToString()
ค่า เช่นมากกว่าRED, BLUE, YELLOW
22
คำตอบ:
คุณจำเป็นต้องใช้&
ด้วย~
(ส่วนประกอบ) ของ 'BLUE'
โอเปอเรเตอร์ประกอบกลับด้านหรือ 'พลิก' บิตทั้งหมดสำหรับชนิดข้อมูลที่กำหนด เช่นถ้าคุณใช้AND
ประกอบการ ( &
) มีค่าบางอย่าง (ขอเรียกว่าค่า 'X') และส่วนประกอบของหนึ่งหรือชุดเพิ่มเติมบิต (ขอเรียกบิตเหล่านั้นQ
และเติมเต็มของพวกเขา~Q
) คำสั่งX & ~Q
ล้างบิตใด ๆ ที่ตั้งอยู่ในQ
จากX
และส่งคืนผลลัพธ์
ดังนั้นเมื่อต้องการลบหรือล้างBLUE
บิตคุณต้องใช้คำสั่งต่อไปนี้:
colorsWithoutBlue = colors & ~Blah.BLUE
colors &= ~Blah.BLUE // This one removes the bit from 'colors' itself
คุณยังสามารถระบุหลายบิตเพื่อล้างดังนี้:
colorsWithoutBlueOrRed = colors & ~(Blah.BLUE | Blah.RED)
colors &= ~(Blah.BLUE | Blah.RED) // This one removes both bits from 'colors' itself
หรือสลับกัน ...
colorsWithoutBlueOrRed = colors & ~Blah.BLUE & ~Blah.RED
colors &= ~Blah.BLUE & ~Blah.RED // This one removes both bits from 'colors' itself
ดังนั้นเพื่อสรุป:
X | Q
ชุดบิต Q
X & ~Q
ล้างบิต Q
~X
พลิก / กลับค่าบิตทั้งหมดใน X
colors &= ~( Blah.BLUE | Blah.GREEN );
คำตอบอื่น ๆ นั้นถูกต้อง แต่หากต้องการลบสีน้ำเงินโดยเฉพาะคุณต้องเขียน:
colors &= ~Blah.BLUE;
And not
มัน...............................
Blah.RED | Blah.YELLOW ==
(Blah.RED | Blah.BLUE | Blah.YELLOW) & ~Blah.BLUE;
คิดว่าสิ่งนี้อาจเป็นประโยชน์สำหรับคนอื่นที่สะดุดเหมือนฉัน
ระวังวิธีที่คุณจัดการค่า enum ใด ๆ ที่คุณอาจกำหนดให้มีค่า == 0 (บางครั้งอาจเป็นประโยชน์ในการมีสถานะ Unknown หรือ Idle สำหรับ enum) มันทำให้เกิดปัญหาเมื่อพึ่งพาการดำเนินการจัดการบิตเหล่านี้
นอกจากนี้เมื่อคุณมีค่า enum ที่เป็นการรวมกันของกำลังสองอื่น ๆ เช่น
public enum Colour
{
None = 0, // default value
RED = 2,
BLUE = 4,
GREEN = 8,
YELLOW = 16,
Orange = 18 // Combined value of RED and YELLOW
}
ในกรณีเหล่านี้วิธีการขยายเช่นนี้อาจมีประโยชน์:
public static Colour UnSet(this Colour states, Colour state)
{
if ((int)states == 0)
return states;
if (states == state)
return Colour.None;
return states & ~state;
}
และยังมีวิธี IsSet ที่เทียบเท่ากันซึ่งจัดการค่าที่รวมกัน (แม้ว่าจะเป็นวิธีที่แฮ็ค)
public static bool IsSet(this Colour states, Colour state)
{
// By default if not OR'd
if (states == state)
return true;
// Combined: One or more bits need to be set
if( state == Colour.Orange )
return 0 != (int)(states & state);
// Non-combined: all bits need to be set
return (states & state) == state;
}
Red, Blue, Green
) แทนที่จะเป็นค่าพื้นฐานใช่ไหม?
none
หรือunknown
หรือunset
รายการที่มีค่า == 0 ในหลายกรณีเป็นสิ่งที่ดีที่คุณไม่เคยคิดว่าคุ้มค่าโดยเฉพาะอย่างยิ่งเป็นชุดเริ่มต้นเช่นถ้าคุณเพียง แต่มีสีแดง, สีฟ้าและสีเขียวที่คุณจะต้องเป็นสีแดง ค่าเริ่มต้น (เช่นค่าที่ enum มีเมื่อมันถูกสร้างขึ้นหรือผู้ใช้ไม่ได้แก้ไขหรือไม่?)
1, 2, 4, 8
เป็นค่าของคุณหรือไม่ หากคุณต้องการค่าเริ่มต้นนั่นคือตัวสร้างเริ่มต้นที่ใช่ ฉันชอบที่จะทำให้สิ่งต่าง ๆ มีความชัดเจนที่สุดเท่าที่จะเป็นไปได้เพื่อประโยชน์ในการอ่านและใช้ enum เป็นค่าเริ่มต้นเป็นdefault(int)
( 0
) เมื่อไม่ได้รับค่าใด ๆ แม้ว่าจะเป็นข้อมูลที่นักพัฒนาคนใดรู้จักก็ตาม แก้ไข: โอ้เดี๋ยวก่อนจะทำให้ Unset = 0 ป้องกันบางสิ่งบางอย่างจากการถูกUnset | Blue
?
Red & ~Red
จบด้วยศูนย์คุณจะต้องมีรหัสเพื่อตรวจสอบกรณีนี้และกำหนดUnset
ค่าอย่างชัดเจน)
แล้ว xor (^) ล่ะ?
เนื่องจาก FLAG ที่คุณพยายามลบอยู่นั้นจะมีการทำงาน .. ถ้าไม่คุณจะต้องใช้ &
public enum Colour
{
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;
เพื่อลดความซับซ้อนของค่าสถานะ enum และทำให้การอ่านดีขึ้นโดยหลีกเลี่ยงทวีคูณเราสามารถใช้การเลื่อนบิตได้ (จากบทความที่ดีจบการอภิปรายครั้งใหญ่เกี่ยวกับ Enum Flags )
[FLAG]
Enum Blah
{
RED = 1,
BLUE = 1 << 1,
GREEN = 1 << 2,
YELLOW = 1 << 3
}
และเพื่อล้างบิตทั้งหมด
private static void ClearAllBits()
{
colors = colors & ~colors;
}
คุณสามารถใช้สิ่งนี้:
colors &= ~Blah.RED;