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?
Cách ưa thích để chuyển đổi Enum thành Chuỗi trong .NET 3.5 là gì?
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?
Câu trả lời:
Kể từ C # 6, cách tốt nhất để có được tên của một enum là nameof
toá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.
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ị .
"someEnumValue"
, trong khi bạn sẽ cần nameof(SomeEnum.FooBar)
phải nhận được "FooBar"
.
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);
}
Trong các thử nghiệm của tôi, Enum.GetName
đã nhanh hơn và bằng lãi khá. ToString
Gọ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 ToString
vì 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()
Đâ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)
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 ToString
và GetName
sẽ là GetName
phải xác minh một số điều trước tiên:
GetType
trên giá trị để kiểm tra này..ToString
do đó, 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à .ToString
phươ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 đó .ToString
là cách nhanh nhất để lấy giá trị dưới dạng chuỗi.
Đ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ụngenum.ToString()
,enum.GetNames()
,enum.GetName()
,enum.Format()
hoặcenum.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.
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.
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ả.
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ả. GetName
hoạ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
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