代码之家  ›  专栏  ›  技术社区  ›  CodingWithSpike

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

  •  13
  • CodingWithSpike  · 技术社区  · 17 年前

    所以我在玩更多的属性。NET,并实现了对Type的每次调用。GetCustomAttributes()创建我的属性的新实例。为什么?我认为属性实例基本上是每个MemberInfo的单例,其中1个实例绑定到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
    

    “类加载器”(抱歉,我有更多的Java背景,不完全确定.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总是“false”。

    3 回复  |  直到 17 年前
        1
  •  11
  •   yfeldblum    17 年前

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

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

    这是 documentation 关于属性。

        2
  •  11
  •   Lasse V. Karlsen    7 年前

    创建对象很便宜。

    如果你有一个属性,比如

    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
    );
    

    ?

        3
  •  2
  •   TcKs    17 年前

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

    推荐文章