C#:未分配的局部变量成功 属性 模式匹配

C#: Unassigned local variable with succeeded property pattern match

我有以下代码使用模式匹配与总是成功的 属性 模式:

var result = new { Message = "Hello!" } is { Message: string message };
Console.WriteLine(message);

以上匹配成功(结果为true)。但是,当我尝试打印 message 时,我得到一个:

CS0165: Use of unassigned local variable.

但是,下面的工作:

var result = "Hello!" is { Length: int len };
Console.WriteLine(len);

此外,当我将它与 if 一起使用时,它工作正常:

if (new { Message = "Hello!"} is { Message: string message }) 
{
    Console.WriteLine(message);
}

为什么会出现差异?

Why the discrepancies?

嗯,这是一个编译时错误,并且在编译时,它不知道它会匹配。就编译器而言,result 为假且 message 未分配是绝对有效的 - 因此尝试使用它是编译时错误。

在你的第二个例子中,编译器知道它总是匹配,因为每个字符串都有一个长度,而在第三个例子中你只是试图使用模式变量如果匹配。

这里唯一的oddity/discrepancy是编译器不知道new { Message = "Hello!" }总是匹配{ Message: string message }。我可以理解,因为 Message 对于相同的匿名类型可能为 null ... 更奇怪的是,它看起来不知道它总是会匹配 { Message: var message } (应该匹配对匿名类型实例的任何非空引用,即使 Message 为空)。

我怀疑对于你的字符串示例,编译器“更清楚”字符串文字不能为空,因此模式真的、真的总是匹配——而出于某种原因它不这样做对于匿名类型。

我注意到,如果您将字符串文字提取到一个单独的变量中,编译器不知道它会始终匹配:

string text = "hello";
var result = text is { Length: int length };
// Use of unassigned local variable
Console.WriteLine(length);

怀疑这是因为字符串文字是一个常量表达式,并且编译器实际上对它可以预测常量表达式的内容更有信心。

我同意它看起来 有点 奇怪,但如果这真的影响了很多实际代码,我会感到惊讶 - 因为你不倾向于对字符串进行模式匹配文字,我会说这里的意外部分是字符串文字匹配。