gpt4 book ai didi

c# - 奇怪的异常行为......为什么?

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

我制作了一个受 C++ 的 std::numeric_limits 启发的类(class)用于获取类型的最小值和最大值。它使用反射填充两个静态只读成员以读出 MaxValue。和 MinValue类型的属性。如果 T 则抛出异常没有那个属性。

public class Limits<T>
{
public static readonly T MaxValue = Read("MaxValue");
public static readonly T MinValue = Read("MinValue");

private static T Read(string name)
{
FieldInfo field = typeof(T).GetField(name, BindingFlags.Public | BindingFlags.Static);

if (field == null)
{
throw new ArgumentException("No " + name + " property in " + typeof(T).Name);
}

return (T)field.GetValue(null);
}
}

现在,当我逐步执行以下程序时,我看到了一些奇怪的行为。

    try
{
Console.WriteLine(Limits<int>.MaxValue);
Console.WriteLine("1");
Console.WriteLine(Limits<object>.MaxValue);
}
catch
{
Console.WriteLine("2");
}

读取 MaxValue 时有一个断点属性(property)。单步执行 Limits<int> 时命中断点并读取属性。然后在执行WriteLine("1")之前再次断点读取Limits<object> .这会引发异常,因为 object没有MaxValue所以人们会期望在 Main 中捕获异常。但这并没有发生,WriteLine("1")被执行,然后异常被捕获....这是为什么? CLR 是否存储异常直到实际行被执行?

最佳答案

来自 static field initialization 上的 C# 语言规范:

If a static constructor (Section 10.11) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.

这意味着:

  • 用户无法直接控制此初始化过程何时运行。
  • 保证在使用字段之前运行一次。

如果在此过程中抛出异常,该类型将在 AppDomain 的剩余生命周期内变得不可用,并且每次您尝试使用该类型时,您都会得到一个 TypeInitializationException。抛出(内部异常是原始异常)检查 the msdn在静态构造函数上。出于这些目的,Limits<int>Limits<object>被认为是不同的类型,所以你仍然可以使用 Limits<int> .

这就是为什么在尝试获取 Limits<object>.MaxValue 时出现异常的原因,因为 clr 为您调用了初​​始化代码并存储了异常,因此可以将其作为 TypeInitializationException 抛出每次使用它。

还需要注意的是,所有静态字段都将在第一次使用该类型之前进行初始化。因此,您可以将以下静态属性添加到您的静态类中:

public static T Default = default(T);

然后按如下方式更改您的测试程序:

static void Main(string[] args)
{
for (int x = 0; x < 3; x++)
{
try
{
Console.WriteLine(Limits<int>.Default);
Console.WriteLine("1");
Console.WriteLine(Limits<object>.Default);
}
catch (TypeInitializationException e)
{
Console.WriteLine("TypeInitializationException: " + e.Message);
}
}
Console.ReadKey();
}

您没有直接使用 MaxValue 静态字段,但是因为您正在使用该类型(通过访问默认值),所有静态字段仍在首次使用该类型之前进行初始化。您还会注意到,您将获得相同的异常 3 次,总是在写入 Limits.Default 和“1”之后。

关于c# - 奇怪的异常行为......为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25258084/

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