这是它的编译方式:
class Program
{
delegate void Message();
private static void GoodMooning()
{
Console.WriteLine("Доброе утро");
}
private static void GoodEvening()
{
Console.WriteLine("Добрый вечер");
}
static void Main(string[] args)
{
Message message;
if(DateTime.Now.Hour < 12)
{
message = GoodMooning;
}
else
{
message = GoodEvening;
}
Console.WriteLine(DateTime.Now.Hour);
message();
Console.ReadKey();
}
}
但它不会像这样编译并写出消息变量未初始化:
class Program
{
delegate void Message();
private static void GoodMooning()
{
Console.WriteLine("Доброе утро");
}
private static void GoodEvening()
{
Console.WriteLine("Добрый вечер");
}
static void Main(string[] args)
{
Message message;
int a = 2;
if(a < 12)
{
message = GoodMooning;
}
message();
Console.ReadKey();
}
}
在第一个变体中,它被编译,因为在调用委托之前,它无论如何都会获取值,而在第二个变体中,消息只有在条件为 true 时才会获取值
DateTime.Now.Hour < 12
,因此不会发生编译。理论上,可以简单地初始化消息null
并且代码将编译。如果它
a
是一个常量,它将编译。并且变量的值不在编译器的权力范围内,因为它们是在应用程序启动时确定的,而不是编译时确定的。
编译器根本不知道条件的结果是什么,因此会警告您该变量未初始化。你可以修复它。
或者您可以将此变量从方法中带入字段,然后它将自动获取默认值。
还有一种解决方案,如果你确定应用程序启动时会满足条件,你可以通过抛出异常来让编译器平静下来。你肯定知道它不会被丢弃,编译器肯定会知道不会使用未初始化的变量——每个人都很高兴。
文档。
在我看来,这就是 CLR 在这种情况下的工作方式。当前时间值的计算晚于检查委托对象的初始化。为什么?因为当设置一个显式值 if (true) - 代码编译没有错误。