gpt4 book ai didi

c# - 什么时候为自定义属性类调用析构函数?

转载 作者:行者123 更新时间:2023-11-30 12:36:28 24 4
gpt4 key购买 nike

假设我有这个类:

[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?
}
}

最佳答案

在 Reflector 中调用 GetCustomAttributes 的示例之后,代码的托管部分(即它转换到运行时并成为外部调用的点)位于 CustomAttribute.GetCustomAttributes 中。

此时,该方法正在检查正在为其加载属性的对象周围的元数据字节。

那里有代码,然后进一步反射以找到正在调用的运行时构造函数。例如

[MyAttribute]

会调用默认值,而

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

将调用采用(Int, String, Type) 的构造函数。

我在那里看不到任何证据表明执行了任何实例缓存,因此这意味着属性实例是在反射(reflect)它们时按需创建的。

证明

上述托管运行时转换发生在 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 类型的实例的方法 m 的所有“实例”(在引号中,因为方法当然只存储在内存中一次)。

因此,一旦代码中对它的所有引用都被清空,GC 就可以使用该属性。该属性的所有成员也是如此。

因此,使用 GetCustomAttributes() 检索属性、使用它然后丢弃引用的方法刚刚释放了该属性的一个新实例,以便 GC 在需要时进行清理。

因此 - 属性实例受与所有类实例完全相同的内存管理和生命周期规则的约束;因此,@PieterG 在他的回答中所说的是正确的——在释放对该属性的所有引用后,可以随时调用析构函数。

关于c# - 什么时候为自定义属性类调用析构函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3235302/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com