Когда вызыватель вызывается для пользовательского класса атрибута?

Скажем, у меня есть этот класс:

[AttributeUsage(AttributeTargets.Method)] 
public class MyAttribute : Attribute 
{ 
  public MyAttribute() 
  { 
    // Do stuff
  }

  ~MyAttribute()
  {
    // When is this called? When the function ends? Whenever the GC feels like?
  }
}

2 ответа

Решение

После примера вызова метода GetCustomAttributes в Reflector управляемая часть кода (т. Е. Точка, в которой он переходит в среду выполнения и становится внешним вызовом) отключается в CustomAttribute.GetCustomAttributes.

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

Там есть код, который затем делает дальнейшие размышления, чтобы найти вызываемый конструктор времени выполнения. Например

[MyAttribute]

Будет вызывать по умолчанию, тогда как

[MyAttribute(1, "hello", typeof(T))]

Будет вызывать конструктор, который принимает (Int, String, Type),

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

доказательство

Вышеупомянутый переход управляемой среды выполнения происходит в CustomAttribute._CreateCaObject. Хотя нелегко статически проанализировать, действительно ли этот метод кеширует экземпляры, которые он создает (потенциально он получает достаточно информации о состоянии в виде указателя буфера памяти, предположительно указывающего место в метаданных, где находится объявление атрибута), мы можем посмотреть на факты:

  • Конструктор всегда вызывается, и
  • Новые параметры конструктора всегда читаются и вводятся.

Это говорит мне, что атрибут всегда создается.

Конечно, мы можем проверить это, написав кусок кода в тесте.

[TestMethod]
public void TestMethod1()
{
  //if running in MSTest you have to allow for the test runner to reflect 
  //over the class as it looks for the TestClass attribute - therefore if our
  //assumption is correct that a new instance is always constructed when 
  //reflecting, our counter check should start at 2, not 1.
  Type t = typeof(AttributeTest);
  var attributes = 
    t.GetCustomAttributes(typeof(AttributeTest.TheAttributeAttribute), false);  
  //check counter
  Assert.AreEqual(2, AttributeTest.TheAttributeAttribute.Counter);
  var attributes2 = 
    t.GetCustomAttributes(typeof(AttributeTest.TheAttributeAttribute), false);
  //should be one louder (sorry, 'one bigger' - the Spinal Tap influence :) )
  Assert.AreEqual(3, AttributeTest.TheAttributeAttribute.Counter);
}

[TheAttribute]
public class AttributeTest
{
  public class TheAttributeAttribute : Attribute
  {
    static int _counter = 0;

    public static int Counter { get { return _counter; } }

    public TheAttributeAttribute()
    {
      _counter++;
      Console.WriteLine("New");
    }
  }
}

Поэтому эффективное использование атрибутов метаданных будет заключаться в том, чтобы кэшировать их в коде пользователя, если, конечно, атрибут не является изменяемым каким-либо образом, что делает его неприменимым для всех экземпляров данного T или все "экземпляры" (в кавычках, потому что метод хранится в памяти только один раз) метода m для экземпляров типа T ).

После этого, следовательно, атрибут становится доступным для GC, как только все ссылки на него в коде обнуляются. То же самое верно и для всех членов этого атрибута.

Поэтому метод, который использует GetCustomAttributes() для извлечения атрибута, использует его, а затем выбрасывает ссылку, только что выпустил новый экземпляр этого атрибута для очистки GC, когда это необходимо.

Следовательно - экземпляры атрибутов регулируются точно такими же правилами управления памятью и правилами жизни, что и все экземпляры классов; поэтому то, что @PieterG говорит в своем ответе, является правильным - деструктор может быть вызван в любое время после того, как все ссылки на этот атрибут были освобождены.

Всякий раз, когда GC чувствует, как это

Деструкторы не могут быть вызваны. Они вызываются автоматически.

Деструкторы (Руководство по программированию в C#)

Другие вопросы по тегам