.NET属性:为什么GetCustomAttributes()每次都会创建一个新的属性实例?

时间:2009-01-06 16:47:04

标签: .net performance attributes

所以我在.NET中使用属性更多地玩,并意识到每次调用Type.GetCustomAttributes()都会创建一个属性的新实例。这是为什么?我认为属性实例基本上是一个single-each-MemberInfo,其中一个实例绑定到Type,PropertyInfo等...

这是我的测试代码:

using System;

namespace AttribTest
{
[AttributeUsage(AttributeTargets.Class)]
class MyAttribAttribute : Attribute
{
    public string Value { get; set; }

    public MyAttribAttribute()
        : base()
    {
        Console.WriteLine("Created MyAttrib instance");
    }
}

[MyAttrib(Value = "SetOnClass")]
class MyClass
{
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Getting attributes for MyClass.");
        object[] a = typeof(MyClass).GetCustomAttributes(false);
        ((MyAttribAttribute)a[0]).Value = "a1";

        Console.WriteLine("Getting attributes for MyClass.");
        a = typeof(MyClass).GetCustomAttributes(false);
        Console.WriteLine(((MyAttribAttribute)a[0]).Value);

        Console.ReadKey();
    }
}
}

现在如果要实现属性,我希望输出为:

Created MyAttrib instance
Getting attributes for MyClass.
Getting attributes for MyClass.
a1

“class loader”(抱歉,我有更多Java背景,不是100%确定.net如何加载其类型)将编译MyClass,并创建MyAttribAttribute的实例,并将它们存储在某处。 (如果这是Java,可能是堆中的Perm Gen)然后,对GetCustomAttributes()的2次调用将返回相同的早期创建的实例。

但实际输出是:

Getting attributes for MyClass.
Created MyAttrib instance
Getting attributes for MyClass.
Created MyAttrib instance
SetOnClass

那么......为什么?似乎为每个调用创建所有这些对象的新实例有点过分,并且对性能/内存管理不利。有没有办法总是一遍又一遍地得到同一个实例?

任何人都有任何想法为什么这样设计?

我关心的原因是因为我创建了一个内部保存一些验证信息的自定义属性,所以在属性中我基本上有一个“私有bool验证”,我设置为true。验证的东西需要一段时间,所以我不想每次都运行它。现在的问题是,每次我获取属性时它都会创建一个新的属性实例,Validated总是“false”。

3 个答案:

答案 0 :(得分:11)

属性不作为对象存储在内存中,它们仅作为元数据存储在程序集中。当你查询它时,它将被构造并返回,并且通常属性是一次性对象,因此运动时保留它们以防万一你再次需要它们可能会浪费大量内存。

简而言之,您需要找到另一种存储共享信息的方式。

这是关于属性的[MSDN](http://msdn.microsoft.com/en-us/library/5x6cd29c(VS.71%29.aspx)页面。

答案 1 :(得分:10)

对象创建很便宜。

如果你有像

这样的属性
public class MyAttribute : Attribute {
    public virtual string MyText { get; set; }
}

并将其应用于类似

的类
[MyAttribute(MyText="some text")]
public class MyClass {
}

你检索了一个像

var attr =
    typeof(MyClass).GetCustomAttributes(typeof(MyAttribute), false)
    .Cast<MyAttribute>().Single();

并在其上设置了一些属性,如

attr.MyText = "not the text we started with";

应该发生什么, 会发生什么,下次你打电话

Console.WriteLine(
    typeof(MyClass).GetCustomAttributes(typeof(MyAttribute), false)
    .Cast<MyAttribute>().Single().Name
);

答案 2 :(得分:2)

这是因为属性保存在元数据中。 属性应该用于诸如“用户友好的属性名称”等信息......