使用CustomAttributes和GetCustomAttributes()的优势
我今天注意到我的intellisense中出现了一些新的属性,用于.NET 4.5项目的System.Type
对象。 其中一个名为CustomAttributes
。
我对此很感兴趣,因为我之前已经知道GetCustomAttributes
是最昂贵的reflection调用之一(当然,除了DynamicInvoke
之外)。 据我所知,每次调用GetCustomAttributes
导致调用属性的构造函数(从而调用内存)。 我经常使用单独缓存自定义属性来避免在处理大量类型等时出现性能瓶颈。
所以,我编写了一个测试,看看CustomAttributes
是否比GetCustomAttributes
更GetCustomAttributes
:
static void Main(string[] args) { var sw = Stopwatch.StartNew(); Debug.WriteLine(typeof(Attributed).GetType()); for (int i = 0; i a.AttributeType) .ToList(); } sw.Stop(); Debug.WriteLine("Using .NET 4.5 CustomAttributes property: {0}", sw.Elapsed); sw = Stopwatch.StartNew(); for (int i = 0; i a.GetType()) .ToList(); } sw.Stop(); Debug.WriteLine("Using GetCustomAttributes method: {0}", sw.Elapsed); }
有些测试类:
[Dummy] [Dummy] [Dummy] [Dummy] [Dummy] [Dummy] class Attributed { } [AttributeUsage(AttributeTargets.Class, AllowMultiple=true)] class DummyAttribute : Attribute { public DummyAttribute() { } }
结果令人惊讶:
System.RuntimeType Using .NET 4.5 CustomAttributes property: 00:00:00.1351259 Using GetCustomAttributes method: 00:00:00.0803161
新的CustomAttributes
属性实际上比现有的GetCustomAttributes
方法慢!
进一步调试,我发现没有调用属性构造函数来迭代CustomAttributes
(我预期它,因为它看起来只是在读取元数据)。 但不知何故,它比调用构造函数的GetCustomAttributes
慢。
我的问题
我个人认为使用新属性更具可读性,但成本却低1.5倍。
那么,使用CustomAttributes
而不是GetCustomAttributes()
有什么优势呢?
我假设我们只是检查clas上是否存在某种类型的属性…不使用属性实例上的方法或属性。
您正在制造传统的基准测试错误,这使得许多.NET程序员认为Reflection很慢。 比实际更慢。 反思是非常懒惰的,当你不使用它时你不付钱。 这使您的第一次测量包括将元数据页面错误输入RAM并设置类型信息reflection缓存的所有成本。 该成本未包含在第二次测量中,使得GetCustomAttributes()看起来比实际更好。
始终在基准代码周围包含一个循环,运行10次。 你现在会看到CustomAttributes属性实际上并不那么慢,我测量它(大约)0.083对0.063秒,慢30%。
需要在.NET 4.5中添加CustomAttributes属性以支持WinRT的语言投影。 您不能在Store,Phone或PCL项目中使用GetCustomAttributes()。 WinRT中的reflection是非常不同的,它是基于COM的API的不可避免的副作用。 实现代码足以让任何人的眼睛流血,但大致的概述是该属性是用C#实现的,并且该方法是在CLR中实现的。 C#代码需要做更多工作来处理语言投影细节,因此不可避免地要慢一些。
因此,只需继续使用GetCustomAttributes(),必要时使用该属性。 30%的速度差异并不是影响风格和可读性的重要原因,应用您的常识。