Dot-Net

.NET 屬性:為什麼 GetCustomAttributes() 每次都創建一個新的屬性實例?

  • July 2, 2019

所以我在 .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 始終為“假”。

對象創建很便宜。

如果你有一個像

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

?

屬性不作為對象儲存在記憶體中,它們僅作為元數據儲存在程序集中。當您查詢它時,它將被構造並返回,並且通常屬性是一次性對象,因此執行時保留它們以防萬一您再次需要它們可能會浪費大量記憶體。

簡而言之,您需要找到另一種方式來儲存您的共享資訊。

這是關於屬性的文件。

引用自:https://stackoverflow.com/questions/417275