วิธีตรวจสอบว่าค่าสตริงอยู่ในรายการ Enum หรือไม่


92

?age=New_Bornในสตริงแบบสอบถามของฉันฉันมีตัวแปรอายุ

มีวิธีตรวจสอบว่าค่าสตริงนี้New_Bornอยู่ในรายการ Enum ของฉันหรือไม่

[Flags]
public enum Age
{
    New_Born = 1,
    Toddler = 2,
    Preschool = 4,
    Kindergarten = 8
}

ตอนนี้ฉันสามารถใช้คำสั่ง if ได้ แต่ถ้ารายการ Enum ของฉันใหญ่ขึ้น ผมอยากหาวิธีที่ดีกว่านี้ ฉันกำลังคิดจะใช้ Linq แต่ไม่แน่ใจว่าจะทำอย่างไร


3
Enum.IsDefinedไม่โอเค?
leppie

คำตอบ:


155

คุณสามารถใช้ได้:

 Enum.IsDefined(typeof(Age), youragevariable)

IsDefined ต้องการอินสแตนซ์ Enum เพื่อตรวจสอบ
Viacheslav Smityukh

9
โปรดจำไว้ว่าEnum.IsDefined()เป็นกรณีที่ละเอียดอ่อน! นั่นไม่ใช่ "วิธีแก้ปัญหาสากล"
Cheshire Cat

7
โดยปกติแนะนำว่าไม่ควรใช้ IsDefined เนื่องจาก Is ใช้การสะท้อนการโทรไปยัง IsDefined เป็นการโทรที่มีราคาแพงมากในแง่ของประสิทธิภาพและ CPU ใช้ TryParse แทน (เรียนรู้จาก pluralsight.com)
Weihui Guo

41

คุณสามารถใช้เมธอด Enum.TryParse:

Age age;
if (Enum.TryParse<Age>("New_Born", out age))
{
    // You now have the value in age 
}

5
สิ่งนี้มีให้เฉพาะ ณ . NET 4
Gary Richter

2
ปัญหานี้คือมันจะคืนค่าจริงหากคุณระบุจำนวนเต็มใด ๆ (ฉันหมายถึงสตริง "New_Born" แทน)
Romain Vincent


2

ฉันมีวิธีการขยายที่ใช้งานง่ายซึ่งใช้ TryParse เนื่องจาก IsDefined นั้นคำนึงถึงตัวพิมพ์เล็กและใหญ่

public static bool IsParsable<T>(this string value) where T : struct
{
    return Enum.TryParse<T>(value, true, out _);
}

1

คุณควรใช้ Enum.TryParse เพื่อบรรลุเป้าหมายของคุณ

นี่คือตัวอย่าง:

[Flags]
private enum TestEnum
{
    Value1 = 1,
    Value2 = 2
}

static void Main(string[] args)
{
    var enumName = "Value1";
    TestEnum enumValue;

    if (!TestEnum.TryParse(enumName, out enumValue))
    {
        throw new Exception("Wrong enum value");
    }

    // enumValue contains parsed value
}

1

ฉันรู้ว่านี่เป็นเธรดเก่า แต่นี่เป็นวิธีการที่แตกต่างกันเล็กน้อยโดยใช้แอตทริบิวต์ใน Enumerates จากนั้นเป็นคลาสตัวช่วยเพื่อค้นหาการแจกแจงที่ตรงกัน

ด้วยวิธีนี้คุณสามารถมีการแมปหลายรายการในการแจงนับเดียว

public enum Age
{
    [Metadata("Value", "New_Born")]
    [Metadata("Value", "NewBorn")]
    New_Born = 1,
    [Metadata("Value", "Toddler")]
    Toddler = 2,
    [Metadata("Value", "Preschool")]
    Preschool = 4,
    [Metadata("Value", "Kindergarten")]
    Kindergarten = 8
}

ด้วยคลาสตัวช่วยของฉันแบบนี้

public static class MetadataHelper
{
    public static string GetFirstValueFromMetaDataAttribute<T>(this T value, string metaDataDescription)
    {
        return GetValueFromMetaDataAttribute(value, metaDataDescription).FirstOrDefault();
    }

    private static IEnumerable<string> GetValueFromMetaDataAttribute<T>(T value, string metaDataDescription)
    {
        var attribs =
            value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof (MetadataAttribute), true);
        return attribs.Any()
            ? (from p in (MetadataAttribute[]) attribs
                where p.Description.ToLower() == metaDataDescription.ToLower()
                select p.MetaData).ToList()
            : new List<string>();
    }

    public static List<T> GetEnumeratesByMetaData<T>(string metadataDescription, string value)
    {
        return
            typeof (T).GetEnumValues().Cast<T>().Where(
                enumerate =>
                    GetValueFromMetaDataAttribute(enumerate, metadataDescription).Any(
                        p => p.ToLower() == value.ToLower())).ToList();
    }

    public static List<T> GetNotEnumeratesByMetaData<T>(string metadataDescription, string value)
    {
        return
            typeof (T).GetEnumValues().Cast<T>().Where(
                enumerate =>
                    GetValueFromMetaDataAttribute(enumerate, metadataDescription).All(
                        p => p.ToLower() != value.ToLower())).ToList();
    }

}

จากนั้นคุณสามารถทำสิ่งที่ชอบ

var enumerates = MetadataHelper.GetEnumeratesByMetaData<Age>("Value", "New_Born");

และเพื่อความสมบูรณ์นี่คือแอตทริบิวต์:

 [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = true)]
public class MetadataAttribute : Attribute
{
    public MetadataAttribute(string description, string metaData = "")
    {
        Description = description;
        MetaData = metaData;
    }

    public string Description { get; set; }
    public string MetaData { get; set; }
}

0

ในการแยกวิเคราะห์อายุ:

Age age;
if (Enum.TryParse(typeof(Age), "New_Born", out age))
  MessageBox.Show("Defined");  // Defined for "New_Born, 1, 4 , 8, 12"

หากต้องการดูว่ามีการกำหนดไว้หรือไม่:

if (Enum.IsDefined(typeof(Age), "New_Born"))
   MessageBox.Show("Defined");

แฟล็กอาจไม่ใช่สิ่งที่ถูกต้องทั้งนี้ขึ้นอยู่กับวิธีที่คุณวางแผนจะใช้Ageenum อย่างที่คุณทราบบ่งชี้ว่าคุณต้องการอนุญาตหลายค่า (เช่นเดียวกับในรูปแบบบิต) จะคืนค่าเท็จเนื่องจากมีหลายค่า[Flags]IsDefinedAge.Toddler | Age.Preschool


2
ควรใช้TryParseเนื่องจากเป็นอินพุตที่ไม่ได้รับการยืนยัน
Servy

1
MessageBox ไม่สมเหตุสมผลในสภาพแวดล้อมเว็บ
Servy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.