แปลง Enum เป็น String


163

วิธีใดที่ต้องการแปลง Enum เป็น String ใน. NET 3.5

  • Enum.GetName
  • Enum.Format
  • ToString

เหตุใดฉันจึงควรเลือกหนึ่งในสิ่งเหล่านี้เหนือสิ่งอื่นใด มันทำงานได้ดีขึ้นหรือไม่


10
ฉันค้นหาและไม่พบสิ่งที่ซ้ำ หากคุณสามารถให้ลิงค์ฉันจะลบคำถามนี้
Eric Weilnau

1
บางครั้งการใช้คำสั่ง switch ไม่ใช่วิธีปฏิบัติที่ดีที่สุด (เมื่อคุณมีจำนวนมาก) คุณสามารถใช้ Dict <> แทน
Guy L

1
หากคุณต้องการประสิทธิภาพที่ดีขึ้นคุณสามารถใช้ระดับที่อธิบายไว้ในบทความนี้codeproject.com/KB/dotnet/enum.aspx การใช้งานจะมีลักษณะดังนี้ Enum <YourEnum> .ToString (yourValue) หรือ Enum <YourEnum> .ToString ((int) yourValue ของคุณ)
ideafixxxer

5
การเขียนโค้ดเพื่อไม่ทำลาย dotfuscation เป็นสิ่งที่ดีเลิศของหางที่กระดิกสุนัข ผู้ผลิต SW ไม่ได้คิดว่า "มาสร้างแอพที่ยอดเยี่ยมกันเถอะเพื่อ dotfuscator มีบางอย่างที่ต้องทำ" มี Dofuscator เพื่อช่วยอำนวยความสะดวกในการพัฒนา SW ถ้ามันทำไม่ได้ ... ทำได้!
micahhoover

คำตอบ:


127

ในฐานะของ C # 6 วิธีที่ดีที่สุดในการรับชื่อของ enum คือnameofโอเปอเรเตอร์ใหม่:

nameof(MyEnum.EnumValue);

// Ouputs
> "EnumValue"

สิ่งนี้ทำงานได้ในเวลารวบรวมโดยการแทนที่ enum ด้วยสตริงในผลลัพธ์ที่คอมไพล์ซึ่งหมายความว่านี่เป็นวิธีที่เร็วที่สุดที่เป็นไปได้

การใช้ชื่อ enum ใด ๆ จะรบกวนการทำให้งงงวยของรหัสถ้าคุณคิดว่าการทำให้งอแงของชื่อ Enum นั้นมีความคุ้มค่าหรือสำคัญ - นั่นอาจเป็นคำถามอื่นทั้งหมด


11
สิ่งนี้สมควรได้รับความสนใจมากขึ้น ข้อ จำกัด ที่ชัดเจนแม้จะมีเช่นข้อกำหนดสำหรับการรวบรวมเวลารวบรวม ในความคิดของฉันนี้ควรเป็นที่ต้องการเมื่อใดก็ตามที่เป็นไปได้ 'เปลี่ยนชื่อ' และ 'ค้นหาการอ้างอิงทั้งหมด' พิจารณาด้วยเช่นกันซึ่งอาจหลีกเลี่ยงสายเวทและค่าคงที่ซ้ำซ้อน
Timo

1
ดังนั้นฉันเดาว่ามันจะไม่ทำงานเมื่อกำหนดค่า enum ที่รันไทม์? เช่น MyEnum variableEnum; variableEnum = setEnumValueMethod (); nameof (variableEnum);
Maxter

1
@ Maxter ไม่เป็นnameof(variableEnum)ไป"variableEnum"ได้ มันสะท้อนให้เห็นถึง (เวลาที่สร้าง) ชื่อของสนาม / คุณสมบัติ / พระราม / ตัวแปรไม่คุ้มค่า
Keith

ท่าน น่าเสียดายที่ไม่สามารถใช้งานได้ถ้าคุณทำเช่นนี้: var someEnumvalue = SomeEnum.FooBar; nameof (someEnumvalue);
Squibly

1
@Squibly ใช่ว่าจะกลับมา"someEnumValue"ในขณะที่คุณจะต้องที่จะได้รับnameof(SomeEnum.FooBar) "FooBar"
Keith

93

ทำงานให้กับโครงการของเรา ...

public static String convertToString(this Enum eff)
{
    return Enum.GetName(eff.GetType(), eff);
}

public static EnumType converToEnum<EnumType>(this String enumValue)  
{
    return (EnumType) Enum.Parse(typeof(EnumType), enumValue);
}

7
Enum.GetName รับค่าเป็นอาร์กิวเมนต์วัตถุ ซึ่งหมายความว่าค่าจะถูกบรรจุอยู่ในกล่องและจะทำให้ทรัพยากร CPU ในการจัดสรรและในการรวบรวมขยะ หากการดำเนินการนี้ใช้เวลามาก Enum.GetName จะมีปริมาณงานที่ต่ำกว่าการแคชค่าในพจนานุกรมและค้นหาชื่อที่นั่น
Ran

@ รันดังนั้นวิธีการแก้ปัญหาซึ่งจะใช้แทนอะไร?
shaijut

นี่ควรเป็นคำตอบ
Squibly

ทำให้โครงการของฉันช้าลง toString () เร็วขึ้น
d2k2

29

ในการทดสอบของฉันEnum.GetNameเร็วขึ้นและมีอัตรากำไรที่เหมาะสม ภายในสายToString จากแหล่งที่มาสำหรับ. NET 4.0 สิ่งสำคัญ:Enum.GetName

public override String ToString()
{
     return Enum.InternalFormat((RuntimeType)GetType(), GetValue());
}

private static String InternalFormat(RuntimeType eT, Object value)
{
    if (!eT.IsDefined(typeof(System.FlagsAttribute), false))
    {
        String retval = GetName(eT, value); //<== the one
        if (retval == null)
            return value.ToString();
        else
            return retval;
    }
    else
    {
        return InternalFlagsFormat(eT, value);
    }
}

ฉันไม่สามารถบอกได้ว่าเป็นเหตุผลที่แน่นอน แต่การทดสอบสถานะนั้นเร็วกว่าอีกอัน การโทรทั้งสองนี้เกี่ยวข้องกับการชกมวย (อันที่จริงแล้วพวกมันคือการสะท้อนการโทร

การตั้งค่าการทดสอบ : enum ด้วยค่า 8 ค่าหมายเลข จากการวนซ้ำ = 1000000

ผลลัพธ์ : Enum.GetName => 700 ms, ToString => 2000 ms

หากความเร็วไม่ชัดเจนฉันจะไม่แคร์และใช้ToStringเนื่องจากมันมีสายที่สะอาดกว่ามาก ความคมชัด

Enum.GetName(typeof(Bla), value)

กับ

value.ToString()

25

Enum.GetName ( ... )

นี่เป็นวิธีที่หรูหราที่สุดที่มีไว้สำหรับมัน

var enumValueString = Enum.GetName(typeof (MyEnum), MyEnum.MyValue);

แม้ว่าฉันจะไม่เห็นปัญหาใด ๆ กับการโทร.ToString()เพราะสั้นกว่า

var enumValueString = MyEnum.MyValue.ToString();

ด้วยไวยากรณ์ C # 6 ใหม่คุณสามารถใช้:

nameof(MyEnum.MyValue)

20

InternalGetValueAsStringทั้งหมดเหล่านี้ภายในสิ้นสุดการเรียกวิธีการที่เรียกว่า ความแตกต่างระหว่างToStringและGetNameจะต้องGetNameมีการตรวจสอบบางสิ่งก่อน:

  1. ประเภทที่คุณป้อนไม่ใช่ค่าว่าง
  2. ประเภทที่คุณป้อนคือในความเป็นจริงการแจงนับ
  3. ค่าที่คุณส่งผ่านไม่เป็นค่าว่าง
  4. ค่าที่คุณส่งผ่านนั้นเป็นประเภทที่การแจงนับสามารถใช้งานได้จริงเนื่องจากเป็นประเภทพื้นฐานหรือประเภทของการแจงนับเอง มันใช้GetTypeกับค่าในการตรวจสอบนี้

.ToStringไม่ต้องกังวลเกี่ยวกับปัญหาใด ๆ ข้างต้นเพราะมันถูกเรียกบนอินสแตนซ์ของคลาสเองและไม่ใช่ในเวอร์ชันที่ส่งผ่านดังนั้นเนื่องจากความจริงที่ว่า.ToStringวิธีการไม่มีปัญหาการตรวจสอบที่เหมือนกัน เป็นวิธีคงที่ฉันจะสรุปว่า.ToStringเป็นวิธีที่เร็วที่สุดเพื่อให้ได้ค่าเป็นสตริง


2
คุณไปตรวจสุขภาพที่ไหน แอสเซมบลีเวอร์ชันคืออะไร ฉันได้รับผลลัพธ์ที่แตกต่างกันมาก
nawfal

17

ดีที่สุดที่ฉันสามารถหาได้คือคำถามที่ไม่เกี่ยวข้องใน MSDNซึ่งมีข้อมูลโค้ด XML ที่ตอบคำถามนี้ ใด ๆ ของวิธีการเหล่านี้ส่วนใหญ่มีข้อบกพร่องเดียวกันพวกเขาเรียกenum.toString()ที่ไม่ได้ทำงานอย่างถูกต้องเมื่อใช้Dotfuscation ความกังวลอื่น ๆ ดูเหมือนจะเกี่ยวข้องกับการชกมวยทางอ้อม (GetName และ Format) น่าเสียดายที่ฉันไม่สามารถหาเหตุผลด้านประสิทธิภาพใด ๆ สำหรับการใช้ข้อใดข้อหนึ่งข้างต้น

ถอดความจากตัวอย่าง XML ,

การส่งผ่าน enum ชนิดบรรจุกล่องไปยัง string รูปแบบ () หรือฟังก์ชันอื่น ๆ อาจส่งผลให้เกิดenum.ToString()การเรียกใช้ สิ่งนี้จะทำให้เกิดปัญหาเมื่อ Dotfuscating คุณไม่ควรใช้enum.ToString(), enum.GetNames(), enum.GetName(), enum.Format()หรือenum.Parse()การแปลง enum สตริง ให้ใช้คำสั่ง switch และแทนชื่อสากลหากจำเป็น


16

Enum.GetName()

Format()จริงๆแล้วมันเป็นเพียงแค่ wrapper ที่GetName()มีฟังก์ชั่นการจัดรูปแบบบางอย่าง (หรือInternalGetValueAsString()แน่นอน) สวยมากเช่นเดียวกับToString() Format()ฉันคิดว่าGetName()เป็นตัวเลือกที่ดีที่สุดเพราะเห็นได้ชัดว่ามันทำอะไรกับทุกคนที่อ่านต้นฉบับ


8

ฉันสร้างวิธีการส่วนขยาย "คำอธิบาย" และแนบกับ enum เพื่อที่ฉันจะได้รับการตั้งชื่อที่ใช้งานง่ายอย่างแท้จริงซึ่งมีช่องว่างและปลอก ฉันไม่เคยชอบใช้ค่า enum เป็นข้อความที่แสดงได้เนื่องจากเป็นสิ่งที่นักพัฒนาซอฟต์แวร์ใช้ในการสร้างโค้ดที่อ่านได้มากขึ้น มันไม่ได้มีไว้สำหรับการแสดงผล UI ฉันต้องการที่จะสามารถเปลี่ยน UI โดยไม่ต้องผ่านและเปลี่ยน enums ทั้งหมด


6

ฉันไม่ทราบว่าวิธี "ที่ต้องการ" คืออะไร (ถาม 100 คนและรับความคิดเห็นที่แตกต่างกัน 100 ข้อ) แต่ทำในสิ่งที่ง่ายที่สุดและใช้งานได้ดี GetNameทำงานได้ แต่ต้องใช้การกดแป้นมากขึ้น ToString()ดูเหมือนว่าจะทำงานได้ดีมาก




0

ToString()ให้ผลลัพธ์ที่ชัดเจนที่สุดจากมุมมองที่อ่านได้ในขณะที่ใช้Enum.GetName()ต้องมีการแยกวิเคราะห์ทางจิตมากกว่าเล็กน้อยเพื่อให้เข้าใจได้อย่างรวดเร็วว่ามันพยายามทำอะไร (เว้นแต่คุณจะเห็นรูปแบบตลอดเวลา)

จากมุมมองประสิทธิภาพบริสุทธิ์ตามที่ระบุไว้แล้วในคำตอบของ @ nawfal Enum.GetName()จะดีกว่า

หากประสิทธิภาพเป็นเป้าหมายของคุณจริง ๆ มันจะเป็นการดียิ่งขึ้นหากต้องการค้นหาล่วงหน้า (โดยใช้พจนานุกรมหรือการทำแผนที่อื่น ๆ )

ใน C ++ / CLI นี้จะมีลักษณะ

Dictionary<String^, MyEnum> mapping;
for each (MyEnum field in Enum::GetValues(MyEnum::typeid))
{
    mapping.Add(Enum::GetName(MyEnum::typeid), field);
}

การเปรียบเทียบโดยใช้ enum 100 รายการและการทำซ้ำ 1000000 รายการ:

Enum.GetName: ~ 800ms
. ToString (): ~ 1600ms
การทำแผนที่พจนานุกรม: ~ 250ms


-3

แบบง่าย: ระบุชื่อลงในรายการ:

List<String> NameList = Enum.GetNames(typeof(YourEnumName)).Cast<string>().ToList()

สวัสดี @Brian ฉันไม่คิดว่าคุณจะต้องแสดงผลลัพธ์ของ GetNames ()
Nic
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.