使用CustomAttributes和GetCustomAttributes()的优势

Los*_*les 6 .net c# reflection custom-attributes

我今天注意到我的intellisense中出现了一些关于System.Type.NET 4.5项目对象的新属性.其中一个叫做CustomAttributes.

我对此很感兴趣,因为我之前已经知道这GetCustomAttributes是最昂贵的反射调用之一(DynamicInvoke当然除此之外).据我了解,每次调用都会GetCustomAttributes导致调用构造函数的属性(以及内存分配).我经常使用单独缓存自定义属性来避免在处理大量类型等时出现性能瓶颈.

所以,我写了一个测试,看看是否CustomAttributes有更高的性能GetCustomAttributes:

static void Main(string[] args)
{
    var sw = Stopwatch.StartNew();

    Debug.WriteLine(typeof(Attributed).GetType());

    for (int i = 0; i < 10000; i++)
    {
        var attrs = typeof(Attributed)
            .CustomAttributes
            .Select(a => a.AttributeType)
            .ToList();
    }

    sw.Stop();
    Debug.WriteLine("Using .NET 4.5 CustomAttributes property: {0}", sw.Elapsed);

    sw = Stopwatch.StartNew();

    for (int i = 0; i < 10000; i++)
    {
        var attrs = typeof(Attributed)
            .GetCustomAttributes(true)
            .Select(a => a.GetType())
            .ToList();
    }

    sw.Stop();
    Debug.WriteLine("Using GetCustomAttributes method: {0}", sw.Elapsed);
}
Run Code Online (Sandbox Code Playgroud)

有些测试类:

[Dummy]
[Dummy]
[Dummy]
[Dummy]
[Dummy]
[Dummy]
class Attributed
{
}

[AttributeUsage(AttributeTargets.Class, AllowMultiple=true)]
class DummyAttribute : Attribute
{
    public DummyAttribute()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

结果令人惊讶:

System.RuntimeType
Using .NET 4.5 CustomAttributes property: 00:00:00.1351259
Using GetCustomAttributes method: 00:00:00.0803161
Run Code Online (Sandbox Code Playgroud)

CustomAttributes属性实际上比现有GetCustomAttributes方法慢!

进一步调试,我发现属性构造函数没有被调用迭代CustomAttributes(我预期,因为它看起来只是在读取元数据).但不知何故,它比GetCustomAttributes调用构造函数要慢.

我的问题

我个人认为使用新属性更具可读性,但成本却低1.5倍.

那么,有什么优势,如果有的话,使用CustomAttributes而不是GetCustomAttributes()

我假设我们只是检查clas上是否存在某种类型的属性...不使用属性实例上的方法或属性.

Han*_*ant 13

您正在制造传统的基准测试错误,这使得许多.NET程序员认为Reflection很慢.比实际更慢.反思是非常懒惰的,当你不使用它时你不付钱.这使得您的第一次测量包括将元数据页面错误输入RAM并设置类型信息反射缓存的所有成本.该成本未包含在第二次测量中,使得GetCustomAttributes()看起来比实际更好.

始终在基准代码周围加一个循环,运行10次.你现在会看到CustomAttributes属性实际上并不那么慢,我测量它(大约)0.083 vs 0.063秒,慢30%.

需要在.NET 4.5中添加CustomAttributes属性以支持WinRT的语言投影.您不能在Store,Phone或PCL项目中使用GetCustomAttributes().WinRT中的反射是非常不同的,它是基于COM的API的不可避免的副作用.实现代码足以让任何人的眼睛流血,但大致的概述是该属性是用C#实现的,并且该方法在CLR中实现.C#代码需要做更多工作来处理语言投影细节,因此不可避免地要慢一些.

因此,只需继续使用GetCustomAttributes(),必要时使用该属性.30%的速度差异并不是影响风格和可读性的重要原因,应用您的常识.