所以我在.NET中使用属性玩了一些,并意识到每次调用Type.GetCustomAttributes()都会创建一个属性的新实例.这是为什么?我认为属性实例基本上是一个single-each-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背景,而不是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".
属性不作为对象存储在内存中,它们仅作为元数据存储在程序集中.当你查询它时,它将被构造并返回,并且通常属性是一次性对象,因此运行时保持它们以防万一你再次需要它们可能会浪费大量内存.
简而言之,您需要找到另一种存储共享信息的方法.
这是关于属性的[MSDN](http://msdn.microsoft.com/en-us/library/5x6cd29c ( VS.71%29.aspx)页面.
对象创建很便宜.
如果你有一个像这样的属性
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().Single();
你在它上面设置了一些属性
attr.MyText = "not the text we started with";
什么应该发生的,什么会发生,下一次调用时
Console.WriteLine( typeof(MyClass).GetCustomAttributes(typeof(MyAttribute), false) .Cast().Single().Name );
?