การแก้ปัญหาข้างต้นไม่ได้เกี่ยวข้องกับ[Flags]
สถานการณ์
วิธีการแก้ปัญหาของฉันด้านล่างอาจมีปัญหาประสิทธิภาพการทำงานบางอย่าง (ฉันแน่ใจว่าใครสามารถเพิ่มประสิทธิภาพในรูปแบบต่างๆ) แต่เป็นหลักมันก็จะพิสูจน์ว่า enum ค่าที่ถูกต้องหรือไม่
มันขึ้นอยู่กับสมมติฐานที่สาม:
- ค่า Enum ใน C # ได้รับอนุญาตให้เป็น
int
อย่างอื่นเท่านั้น
- ชื่อ Enum ใน C # จะต้องเริ่มต้นด้วยตัวอักษร
- ไม่มีชื่อ enum ที่ถูกต้องสามารถเป็นได้ด้วยเครื่องหมายลบ:
-
การเรียกToString()
ใช้ enum ส่งคืนทั้งint
ค่าหนึ่งหากไม่มีการจับคู่ enum (แฟล็กหรือไม่) หากจับคู่ค่า enum ที่ได้รับอนุญาตมันจะพิมพ์ชื่อของการจับคู่ (es)
ดังนั้น:
[Flags]
enum WithFlags
{
First = 1,
Second = 2,
Third = 4,
Fourth = 8
}
((WithFlags)2).ToString() ==> "Second"
((WithFlags)(2 + 4)).ToString() ==> "Second, Third"
((WithFlags)20).ToString() ==> "20"
ด้วยกฎสองข้อนี้เราสามารถสันนิษฐานได้ว่าถ้า. NET Framework ทำงานได้อย่างถูกต้องว่าการเรียกใช้ToString()
เมธอดenum ที่ถูกต้องจะส่งผลให้บางสิ่งที่มีตัวอักษรเป็นตัวอักษรตัวแรก:
public static bool IsValid<TEnum>(this TEnum enumValue)
where TEnum : struct
{
var firstChar = enumValue.ToString()[0];
return (firstChar < '0' || firstChar > '9') && firstChar != '-';
}
ใคร ๆ ก็เรียกมันว่า "แฮ็ค" แต่ข้อดีก็คือโดยอาศัยการปฏิบัติตามEnum
มาตรฐานของ Microsoft และ C # คุณจึงไม่ต้องพึ่งพารหัสหรือเช็คที่อาจเป็นรถของคุณเอง ในสถานการณ์ที่ประสิทธิภาพไม่สำคัญอย่างยิ่งสิ่งนี้จะบันทึกข้อความที่น่ารังเกียจswitch
หรือเช็คอื่น ๆ มากมาย!
แก้ไข
ขอบคุณ @ChaseMedallion ที่ชี้ให้เห็นว่าการใช้งานดั้งเดิมของฉันไม่สนับสนุนค่าลบ สิ่งนี้ได้รับการแก้ไขและมีการทดสอบ
และการทดสอบเพื่อสำรอง:
[TestClass]
public class EnumExtensionsTests
{
[Flags]
enum WithFlags
{
First = 1,
Second = 2,
Third = 4,
Fourth = 8
}
enum WithoutFlags
{
First = 1,
Second = 22,
Third = 55,
Fourth = 13,
Fifth = 127
}
enum WithoutNumbers
{
First, // 1
Second, // 2
Third, // 3
Fourth // 4
}
enum WithoutFirstNumberAssigned
{
First = 7,
Second, // 8
Third, // 9
Fourth // 10
}
enum WithNagativeNumbers
{
First = -7,
Second = -8,
Third = -9,
Fourth = -10
}
[TestMethod]
public void IsValidEnumTests()
{
Assert.IsTrue(((WithFlags)(1 | 4)).IsValid());
Assert.IsTrue(((WithFlags)(1 | 4)).IsValid());
Assert.IsTrue(((WithFlags)(1 | 4 | 2)).IsValid());
Assert.IsTrue(((WithFlags)(2)).IsValid());
Assert.IsTrue(((WithFlags)(3)).IsValid());
Assert.IsTrue(((WithFlags)(1 + 2 + 4 + 8)).IsValid());
Assert.IsFalse(((WithFlags)(16)).IsValid());
Assert.IsFalse(((WithFlags)(17)).IsValid());
Assert.IsFalse(((WithFlags)(18)).IsValid());
Assert.IsFalse(((WithFlags)(0)).IsValid());
Assert.IsTrue(((WithoutFlags)1).IsValid());
Assert.IsTrue(((WithoutFlags)22).IsValid());
Assert.IsTrue(((WithoutFlags)(53 | 6)).IsValid()); // Will end up being Third
Assert.IsTrue(((WithoutFlags)(22 | 25 | 99)).IsValid()); // Will end up being Fifth
Assert.IsTrue(((WithoutFlags)55).IsValid());
Assert.IsTrue(((WithoutFlags)127).IsValid());
Assert.IsFalse(((WithoutFlags)48).IsValid());
Assert.IsFalse(((WithoutFlags)50).IsValid());
Assert.IsFalse(((WithoutFlags)(1 | 22)).IsValid());
Assert.IsFalse(((WithoutFlags)(9 | 27 | 4)).IsValid());
Assert.IsTrue(((WithoutNumbers)0).IsValid());
Assert.IsTrue(((WithoutNumbers)1).IsValid());
Assert.IsTrue(((WithoutNumbers)2).IsValid());
Assert.IsTrue(((WithoutNumbers)3).IsValid());
Assert.IsTrue(((WithoutNumbers)(1 | 2)).IsValid()); // Will end up being Third
Assert.IsTrue(((WithoutNumbers)(1 + 2)).IsValid()); // Will end up being Third
Assert.IsFalse(((WithoutNumbers)4).IsValid());
Assert.IsFalse(((WithoutNumbers)5).IsValid());
Assert.IsFalse(((WithoutNumbers)25).IsValid());
Assert.IsFalse(((WithoutNumbers)(1 + 2 + 3)).IsValid());
Assert.IsTrue(((WithoutFirstNumberAssigned)7).IsValid());
Assert.IsTrue(((WithoutFirstNumberAssigned)8).IsValid());
Assert.IsTrue(((WithoutFirstNumberAssigned)9).IsValid());
Assert.IsTrue(((WithoutFirstNumberAssigned)10).IsValid());
Assert.IsFalse(((WithoutFirstNumberAssigned)11).IsValid());
Assert.IsFalse(((WithoutFirstNumberAssigned)6).IsValid());
Assert.IsFalse(((WithoutFirstNumberAssigned)(7 | 9)).IsValid());
Assert.IsFalse(((WithoutFirstNumberAssigned)(8 + 10)).IsValid());
Assert.IsTrue(((WithNagativeNumbers)(-7)).IsValid());
Assert.IsTrue(((WithNagativeNumbers)(-8)).IsValid());
Assert.IsTrue(((WithNagativeNumbers)(-9)).IsValid());
Assert.IsTrue(((WithNagativeNumbers)(-10)).IsValid());
Assert.IsFalse(((WithNagativeNumbers)(-11)).IsValid());
Assert.IsFalse(((WithNagativeNumbers)(7)).IsValid());
Assert.IsFalse(((WithNagativeNumbers)(8)).IsValid());
}
}