12

所以我在 .NET 中使用了更多的属性,并意识到每次调用 Type.GetCustomAttributes() 都会创建我的属性的一个新实例。这是为什么?我认为属性实例基本上是一个单例每个成员信息,有 1 个实例绑定到类型、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

“类加载器”(对不起,我有更多的 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

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

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

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

4

3 回答 3

11

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

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

这是关于属性的文档。

于 2009-01-06T16:49:02.057 回答
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
);

?

于 2009-01-06T16:55:17.147 回答
2

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

于 2009-01-06T16:51:15.983 回答