为什么 C# 可以检查 'var' 是否为空?

Why can C# check if a 'var' is null?

我有以下代码:

List<IMessage> messageList = new List<IMessage>();

foreach(var msg in messageList)
{
    if(msg != null)
    {

    }
}

如何根据 null 检查 var msg?是什么告诉编译器 varIMessage 而不是 int 或其他不可为 null 的类型?

如果您查看 MSDN 中的示例,它们会为隐式类型变量提供初始值(从而使声明变得显式)。在我的例子中,我什至没有给它一个值,但编译器没有问题。编译器如何知道 msg 可以为空?

编译器会为您推断类型。在基本层面上,当您说:

var x = "foo";

编译器发现表达式的右侧是 string 并分配 x 该类型。

编译器遇到foreach语句时也一样。它确定 IEnumerable 类型(在您的情况下为 IEnumerable<IMessage> )并分配 msg 类型 IMessage.

在您的示例中,您的 messageListList<IMessage> 类型,因此,当您执行

foreach (var m in messageList)

C# 自动知道预期的项目类型(列表中包含的项目,在本例中为 IMessage 对象)并推断 var 将在编译期间转换为 IMessage

var关键字只是语法糖,实际上不是类型。它只是让你的生活更轻松(你不必写实际类型)

编译器知道 msg 可以为空,因为它是静态类型的。静态类型是 IMessage,即使你没有给它命名。

编译器用IMessage代替var的原因是它出现在foreach (varidentifierin collection ) 并且 collection 是实现 IEnumerable<IMessage>.

的类型的表达式

var 的每次出现都会有一些静态替换的类型。 (有可能是dynamic,但是dynamic不是默认的,只能在静态类型推断规则下可以推断的情况下才适用)如果静态类型推断规则找不到要替换的唯一类型,则不允许使用 var

var 的类型总是 在编译时已知。任何无法从语法中推断类型的情况都将是编译时错误。

在这种情况下,您正在迭代 IMessage 的类型化集合,因此编译器知道迭代变量是 IMessage 类型,因此可以为 null。

var 是一个非常具有误导性的关键字。
var 声明一个具有特定数据类型的变量,而不告诉程序员该类型是什么。

你实际申报的是

 foreach (IMessage msg in messageList)

但你必须自己解决这个问题。