首页 > 编程 > .NET > 正文

.NET获取枚举DescriptionAttribute描述信息性能改进的多种方法

2024-07-10 12:47:28
字体:
来源:转载
供稿:网友

一. DescriptionAttribute的普通使用方式

1.1 使用示例

  DescriptionAttribute特性可以用到很多地方,比较常见的就是枚举,通过获取枚举上定义的描述信息在UI上显示,一个简单的枚举定义:

public enum EnumGender{None,[System.ComponentModel.Description("男")]Male,[System.ComponentModel.Description("女")]Female,Other,} 

  本文不讨论DescriptionAttribute的其他应用场景,也不关注多语言的实现,只单纯的研究下获取枚举描述信息的方法。

  一般比较常见的获取枚举描述信息的方法如下,可以在园子里搜索类似的代码非常多。

public static string GetDescriptionOriginal(this Enum @this){var name = @this.ToString();var field = @this.GetType().GetField(name);if (field == null) return name;var att = System.Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute), false);return att == null ? field.Name : ((DescriptionAttribute)att).Description;}

  简单测试下:

Console.WriteLine(EnumGender.Female.GetDescriptionOriginal());Console.WriteLine(EnumGender.Male.GetDescriptionOriginal());Console.WriteLine(EnumGender.Other.GetDescriptionOriginal()); //输出结果: 女 男 Other

1.2 上面的实现代码的问题

  首先要理解特性是什么?

特性:

Attribute特性就是关联了一个目标对象的一段配置信息,存储在dll内的元数据。它本身没什么意义,可以通过反射来获取配置的特性信息。

  因此主要问题其实就是反射造成的严重性能问题:

•1.每次调用都会使用反射,效率慢!
•2.每次调用反射都会生成新的DescriptionAttribute对象,哪怕是同一个枚举值。造成内存、GC的极大浪费!
•3.好像不支持位域组合对象!
•4.这个地方的方法参数是Enum,Enum是枚举的基类,他是一个引用类型,而枚举是值类型,该方法会造成装箱,不过这个问题好像是不可避免的。

  性能到底有多差呢?代码来实测一下:

[Test]public void GetDescriptionOriginal_Test(){var enums = this.GetTestEnums();Console.WriteLine(enums.Count);TestHelper.InvokeAndWriteAll(() =>{System.Threading.Tasks.Parallel.For(0, 1000000, (i, obj) =>{foreach (var item in enums){var a = item.GetDescriptionOriginal();}});});}//输出结果:80TimeSpan:79,881.0000ms //共消耗了将近80秒MemoryUsed:-1,652.7970KBCollectionCount(0):7,990.00 //0代GC回收了7千多次,因为创建了大量的DescriptionAttribute对象 

  其中this.GetTestEnums();方法使用获取一个枚举值集合,用于测试的,集合大小80,执行100w次,相当于执行了8000w次GetDescriptionOriginal方法。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表