Chuyển đổi Enum thành chuỗi


163

Cách ưa thích để chuyển đổi Enum thành Chuỗi trong .NET 3.5 là gì?

  • Enum.GetName
  • Enum.Format
  • ToString

Tại sao tôi nên thích một trong những thứ này hơn những cái khác? Có ai thực hiện tốt hơn?


10
Tôi đã tìm kiếm và không thể tìm thấy một bản sao. Nếu bạn có thể cung cấp một liên kết, tôi sẽ xóa câu hỏi này.
Eric Weilnau

1
đôi khi, sử dụng câu lệnh chuyển đổi không phải là cách thực hành tốt nhất (khi bạn có số lượng lớn), bạn có thể sử dụng Dict <> thay vào đó
Guy L

1
Nếu bạn muốn hiệu suất tốt hơn, bạn có thể sử dụng lớp được mô tả trong bài viết này codeproject.com/KB/dotnet/enum.aspx . Cách sử dụng sẽ giống như Enum <YourEnum> .ToString (yourValue) hoặc Enum <YourEnum> .ToString ((int) yourValue)
ideafixxxer

5
Mã hóa để không phá vỡ dotfuscation là hình ảnh thu nhỏ của cái đuôi vẫy con chó. Các nhà sản xuất SW không nghĩ rằng "Hãy tạo ra một ứng dụng tuyệt vời để dotfuscator có việc phải làm." Dofuscator tồn tại để giúp tạo điều kiện phát triển SW. Nếu nó không thể làm điều đó ... có thể!
micahhoover

Câu trả lời:


125

Kể từ C # 6, cách tốt nhất để có được tên của một enum là nameoftoán tử mới :

nameof(MyEnum.EnumValue);

// Ouputs
> "EnumValue"

Điều này hoạt động vào thời gian biên dịch, với enum được thay thế bằng chuỗi trong kết quả được biên dịch, điều này có nghĩa đây là cách nhanh nhất có thể.

Bất kỳ việc sử dụng tên enum nào đều can thiệp vào mã obfuscation, nếu bạn coi việc giấu tên enum là đáng giá hoặc quan trọng - đó có lẽ là một câu hỏi hoàn toàn khác.


11
Điều này xứng đáng được chú ý nhiều hơn. Giới hạn rõ ràng mặc dù, nghĩa là yêu cầu đầu vào thời gian biên dịch. Theo tôi điều này nên được ưu tiên bất cứ khi nào có thể . 'Đổi tên' và 'tìm tất cả các tài liệu tham khảo' cũng được tính đến, có khả năng tránh các chuỗi ma thuật và các hằng số trùng lặp.
Timo

1
Vì vậy, tôi đoán nó sẽ không hoạt động khi giá trị enum được xác định trong thời gian chạy? Vd: MyEnum biếnEnum; biếnEnum = setEnumValueMethod (); nameof (biếnEnum);
Maxter

1
@Maxter không, như nameof(variableEnum)sẽ có "variableEnum". Nó phản ánh (tại thời điểm xây dựng) tên của trường / thuộc tính / param / biến không phải là giá trị .
Keith

các ngươi tiếc là không hoạt động nếu bạn làm điều này: var someEnumvalue = someEnum.FooBar; nameof (someEnumvalue);
Squingly 11/11/19

@ Có thể có, điều đó sẽ trở lại "someEnumValue", trong khi bạn sẽ cần nameof(SomeEnum.FooBar)phải nhận được "FooBar".
Keith

93

Hoạt động cho dự án của chúng tôi ...

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 lấy giá trị làm đối số. Điều này có nghĩa là giá trị sẽ được đóng hộp và điều này sẽ lãng phí tài nguyên CPU vào việc phân bổ và thu gom rác. Nếu việc này được thực hiện nhiều thời gian, Enum.GetName sẽ có thông lượng thấp hơn nhiều so với lưu trữ các giá trị trong từ điển và tìm kiếm tên ở đó.
Ran

@Ran vậy giải pháp nào, dùng cái gì thay thế?
shaijut

Đây phải là câu trả lời
Squizable

làm cho dự án của tôi chậm hơn toString () nhanh hơn.
d2k2

29

Trong các thử nghiệm của tôi, Enum.GetNameđã nhanh hơn và bằng lãi khá. ToStringGọi nội bộ Enum.GetName. Từ nguồn cho .NET 4.0, các yếu tố cần thiết:

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);
    }
}

Tôi không thể nói đó là lý do chắc chắn, nhưng kiểm tra trạng thái nhanh hơn cái kia. Cả hai cuộc gọi đều liên quan đến quyền anh (thực tế chúng là các cuộc gọi phản xạ, về cơ bản bạn đang truy xuất tên trường) và có thể chậm theo ý thích của bạn.

Kiểm tra thiết lập : enum với 8 giá trị, không. số lần lặp = 1000000

Kết quả : Enum.GetName => 700 ms, ToString => 2000 ms

Nếu tốc độ không đáng chú ý, tôi sẽ không quan tâm và sử dụng ToStringvì nó cung cấp một cuộc gọi sạch hơn nhiều. Tương phản

Enum.GetName(typeof(Bla), value)

với

value.ToString()

25

Enum.GetName (...)

Đây là phương pháp thanh lịch nhất có nghĩa là cho nó.

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

Mặc dù tôi không thấy bất kỳ vấn đề nào với việc gọi .ToString()vì nó đơn giản là ngắn hơn.

var enumValueString = MyEnum.MyValue.ToString();

Với cú pháp C # 6 mới, bạn có thể sử dụng:

nameof(MyEnum.MyValue)

20

Tất cả trong số này kết thúc bằng cách gọi một phương thức được gọi InternalGetValueAsString. Sự khác biệt giữa ToStringGetNamesẽ là GetNamephải xác minh một số điều trước tiên:

  1. Loại bạn đã nhập không có giá trị.
  2. Loại bạn đã nhập, trên thực tế là một bảng liệt kê.
  3. Giá trị bạn chuyển vào không phải là null.
  4. Giá trị bạn truyền vào thuộc loại liệt kê thực sự có thể sử dụng làm loại cơ bản hoặc loại liệt kê. Nó sử dụng GetTypetrên giá trị để kiểm tra này.

.ToStringdo đó, không phải lo lắng về bất kỳ vấn đề nào ở trên, bởi vì nó được gọi là một thể hiện của chính lớp đó và không phải là phiên bản được thông qua, do thực tế là .ToStringphương thức này không có cùng các vấn đề xác minh như các phương thức tĩnh, tôi sẽ kết luận rằng đó .ToStringlà cách nhanh nhất để lấy giá trị dưới dạng chuỗi.


2
bạn đã kiểm tra những thứ này ở đâu? Phiên bản lắp ráp là gì? Tôi nhận được kết quả rất khác nhau.
nawfal

17

Điều tốt nhất tôi có thể tìm thấy là câu hỏi không liên quan này trên MSDN , trong đó có một đoạn mã XML trả lời câu hỏi này. Bất kỳ phương pháp nào trong số này đều có chung một lỗ hổng: chúng gọi enum.toString(), không hoạt động đúng khi sử dụng Dotfuscation . Các mối quan tâm khác dường như liên quan đến quyền anh gián tiếp (GetName và Format). Thật không may, tôi không thể tìm thấy bất kỳ lý do hiệu suất để sử dụng bất kỳ lý do nào ở trên.

Diễn giải từ đoạn xml ,

Truyền một enum được đóng hộp cho chuỗi.Format () hoặc bất kỳ hàm nào khác có thể dẫn đến enum.ToString()việc được gọi. Điều này sẽ gây ra vấn đề khi Dotfuscating. Bạn không nên sử dụng enum.ToString(), enum.GetNames(), enum.GetName(), enum.Format()hoặc enum.Parse()để chuyển đổi một enum thành một chuỗi. Thay vào đó, sử dụng một câu lệnh chuyển đổi, và cũng quốc tế hóa các tên nếu cần thiết.


16

Enum.GetName()

Format()thực sự chỉ là một trình bao bọc xung quanh GetName()với một số chức năng định dạng (hoặc InternalGetValueAsString()chính xác). ToString()là khá nhiều giống như Format(). Tôi nghĩ GetName()là lựa chọn tốt nhất vì nó hoàn toàn rõ ràng những gì nó làm cho bất cứ ai đọc nguồn.


8

Tôi tạo một phương thức mở rộng "Mô tả" và gắn nó vào enum để tôi có thể đặt tên thật thân thiện với người dùng bao gồm khoảng trắng và vỏ. Tôi chưa bao giờ thích sử dụng chính giá trị enum dưới dạng văn bản có thể hiển thị bởi vì đó là thứ chúng tôi phát triển sử dụng để tạo mã dễ đọc hơn. Nó không dành cho mục đích hiển thị UI. Tôi muốn có thể thay đổi giao diện người dùng mà không cần thông qua và thay đổi tất cả.


6

Tôi không biết phương pháp "ưa thích" là gì (hỏi 100 người và nhận 100 ý kiến ​​khác nhau) nhưng làm những gì đơn giản nhất và những gì hiệu quả. GetNamehoạt động nhưng đòi hỏi nhiều tổ hợp phím hơn. ToString()dường như làm công việc rất tốt


1

Đối với người hâm mộ VB:

EnumStringValue = System.Enum.GetName(GetType(MyEnum), MyEnumValue)

0

Điều này cũng sẽ làm việc.

    List<string> names = Enum.GetNames(typeof(MyEnum)).ToList();

0

ToString()đưa ra kết quả rõ ràng nhất từ góc độ dễ đọc, trong khi sử dụng Enum.GetName()đòi hỏi một chút phân tích tinh thần để nhanh chóng hiểu những gì nó đang cố gắng làm (trừ khi bạn nhìn thấy mô hình mọi lúc).

Từ quan điểm hiệu suất thuần túy, như đã được cung cấp trong câu trả lời của @ nawfal, Enum.GetName()là tốt hơn.

Nếu hiệu suất thực sự là mục tiêu của bạn, thì sẽ tốt hơn nếu cung cấp tra cứu trước (sử dụng Từ điển hoặc một số ánh xạ khác).

Trong C ++ / CLI, nó sẽ giống như

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

So sánh bằng cách sử dụng enum của 100 mục và 1000000 lần lặp:

Enum.GetName: ~ 800ms
.ToString (): ~ 1600ms Ánh
xạ từ điển: ~ 250ms


-2

Đơn giản: enum đặt tên vào Danh sách:

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

Xin chào @Brian, tôi không nghĩ bạn cần bỏ kết quả đầu ra của GetNames ()
Nic
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.