Подтвердить что ты не робот

Атрибуты .NET: Почему GetCustomAttributes() каждый раз создает новый атрибут?

Итак, я играл еще немного с атрибутами в .NET и понял, что каждый вызов Type.GetCustomAttributes() создает новый экземпляр моего атрибута. Почему это? Я бы подумал, что экземпляр атрибута будет в основном быть singleton-per-MemberInfo, причем 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). 2 вызова GetCustomAttributes() теперь просто вернут тот же ранее созданный экземпляр.

Но фактический вывод:

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

Итак... почему? Кажется, что создание нового экземпляра всех этих объектов для каждого вызова немного чрезмерно, и это плохо для управления производительностью/памятью. Есть ли способ всегда получать один и тот же экземпляр снова и снова?

У кого-нибудь есть идеи, почему он был разработан таким образом?

Причина, по которой мне все равно, заключается в том, что я создал собственный атрибут, который внутренне хранит некоторую информацию для проверки, поэтому в атрибуте я в основном имею "private bool Validated", который я установил в true. Материал для проверки занимает некоторое время, поэтому я не хочу запускать его каждый раз. Теперь проблема в том, что, поскольку он создает новый экземпляр атрибута каждый раз, когда я получаю атрибуты, Validated всегда "false".

4b9b3361

Ответ 1

Создание объекта дешево.

Если у вас есть атрибут

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

?

Ответ 2

Атрибуты не хранятся в памяти как объекты, они хранятся только как метаданные в сборке. Когда вы запрашиваете его, он будет сконструирован и возвращен, и обычно атрибуты являются одноразовыми объектами, поэтому для среды выполнения их нужно хранить на всякий случай, если они вам понадобятся снова, вероятно, будут тратить много памяти.

Короче говоря, вам нужно найти другой способ хранения вашей общей информации.

Здесь документация по атрибутам.

Ответ 3

Это потому, что атрибуты сохраняются в метаданных. Атрибуты должны использоваться для информации, такой как "удобное имя свойства" и т.д.