12

そのため、.NET で属性をもう少しいじっていたところ、Type.GetCustomAttributes() を呼び出すたびに、属性の新しいインスタンスが作成されることに気付きました。何故ですか?属性インスタンスは基本的に、1 つのインスタンスが Type、PropertyInfo などにバインドされた、MemberInfo ごとの singleton になると思います...

ここに私のテストコードがあります:

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がその型をロードする方法を100%確信していません)がMyClassをコンパイルし、MyAttribAttributeのインスタンスを作成し、それらをどこかに一緒に保存します。(おそらくこれが Java の場合、ヒープ内の Perm Gen) GetCustomAttributes() への 2 回の呼び出しは、以前に作成された同じインスタンスを返すだけです。

しかし、実際の出力は次のとおりです。

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

なぜ?呼び出しごとにこれらすべてのオブジェクトの新しいインスタンスを作成するのは少し過剰であり、パフォーマンス/メモリ管理には適していないようです。常に同じインスタンスを何度も取得する方法はありますか?

なぜこのように設計されたのか、誰にも分かりますか?

私が気にする理由は、内部的にいくつかの検証情報を保持するカスタム属性を作成したためです。そのため、属性には基本的に「プライベートブール検証済み」を true に設定しています。検証には時間がかかるので、毎回実行したくありません。問題は、属性を取得するたびに属性の新しいインスタンスを作成するため、 Validated が常に「false」であることです。

4

3 に答える 3