考虑这个简单的控制台应用程序:
class Program
{
static void Main(string[] args)
{
var human = CreateHuman(args[0]);
Console.WriteLine("Created Human");
Console.ReadLine();
}
public static object CreateHuman(string association)
{
object human = null;
if (association == "is-a")
{
human = new IsAHuman();
}
else
{
human = new HasAHuman();
}
return human;
}
}
public class IsAHuman : Human
{
}
public class HasAHuman
{
public Human Human { get; set; }
}
Human
类在另一个程序集中,比如 HumanAssembly.dll
。如果 HumanAssembly.dll
存在于我们的控制台应用程序的 bin
目录中,一切都会好起来的。正如我们所料,删除它会遇到 FileNotFoundException
。
虽然这部分我不明白。注释human = new IsAHuman();
行,重新编译并删除HumanAssembly.dll
。在这种情况下,控制台应用程序不会抛出任何异常。
我的猜测是 CLR 编译器区分是一个和有一个关联。换句话说,CLR 试图找出并理解并可能加载存在于类定义语句 中的所有类型,但它可以实例化一个类而不知道其中包含什么。但我不确定我的解释。
我找不到很好的解释。对此行为的解释是什么?
最佳答案
您正在看到 JIT 编译器的行为。及时。一个方法直到最后可能的时刻才会被编译,就在它被调用之前。由于您消除了实际构建 Human 对象的需要,因此没有留下强制抖动加载程序集的代码路径。所以你的程序不会崩溃。
最后剩下的对 Human 的引用是 HashAHuman.Human 属性。你不用它。
预测抖动何时需要加载程序集在实践中不是那么简单。当您运行代码的发布版本时,它变得非常难以推理。通常enables the optimizer这是内置在抖动中的,其核心优化策略之一是内联一个方法。为此,它需要在调用之前访问该方法。您需要一个额外的间接级别,一个具有 [MethodImpl(MethodImplOptions.NoInlining)]
属性的额外方法来阻止它进行窥视。这有点深入,始终首先考虑插件架构,例如 MEF。
关于c# - 在 C# 中对这种行为的解释是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25136766/