对象模式匹配导致未初始化的变量
Object pattern matching results in uninitialized variable
查找值是否不是 null
的模式匹配是使用具有相应预期类型的 is
关键字完成的(如有必要,包括强制转换)。模式 !(obj is object instance)
returns true
如果 obj
不是 null
和 false
如果 obj
是 null
。同时如果 obj
不是 null
它被捕获在变量 instance
.
[Fact]
public void Old_pattern_matching_for_non_null_object()
{
var obj = new object();
if (!(obj is object instance)) // false
return;
if (instance is null) // false
throw new Exception("Never reached");
// this does not throw an exception (test passes)
}
在 C#8 中引入了一种新的编写方式,使用 { }
表示 non-null
(无需转换),将代码“简化”为
[Fact]
public void Csharp_8_pattern_matching_for_non_null_object()
{
var obj = new object();
if (!(obj is { } instance)) // false
return;
if (instance is null) // false
throw new Exception("Never reached");
// this does not throw an exception (test passes)
}
在 C#9 中,引入了新关键字 not
,旨在将 !(x is null)
等模式简化为 x is not null
。如果我现在尝试将新的 not
关键字应用于包含 { }
的模式,我会得到一个非常令人惊讶的结果:
[Fact]
public void Csharp_9_pattern_matching_for_non_null_object()
{
var obj = new object();
if (obj is not { } instance) // false
return;
if (instance is null) // true
throw new Exception("Why the heck is this null");
// this does throw an exception (test fails)
}
即使 obj
不是 null
,instance
变量也未初始化。为了得到一个更好的,通过避免 obj
变量 instance
将被初始化:
[Fact]
public void Csharp_9_pattern_matching_for_non_null_object_without_obj_variable()
{
if (new object() is not { } instance) // false
return;
if (instance is null) // false
throw new Exception("Never reached");
// this does not throw an exception (test passes)
}
有人知道这是否是我们想要的行为吗?如果是,其背后的意图是什么?
正如 Yari Halberstadt 所指出的,这实际上是一个编译器错误。我在 Csharplang discussions 上发布了一个关于此的问题,并被告知此问题已得到解决。
正如 canton7 指出的那样,该问题最近已修复,目前尚未发布。
一旦发布,所有示例测试用例都应该通过。根据 this C#9 release blog ,失败的测试用例实际上是一个有效的用例,其中使用了以下示例:
if (e is not Customer c) { throw ... } // if this branch throws or returns...
var n = c.FirstName; // ... c is definitely assigned here
查找值是否不是 null
的模式匹配是使用具有相应预期类型的 is
关键字完成的(如有必要,包括强制转换)。模式 !(obj is object instance)
returns true
如果 obj
不是 null
和 false
如果 obj
是 null
。同时如果 obj
不是 null
它被捕获在变量 instance
.
[Fact]
public void Old_pattern_matching_for_non_null_object()
{
var obj = new object();
if (!(obj is object instance)) // false
return;
if (instance is null) // false
throw new Exception("Never reached");
// this does not throw an exception (test passes)
}
在 C#8 中引入了一种新的编写方式,使用 { }
表示 non-null
(无需转换),将代码“简化”为
[Fact]
public void Csharp_8_pattern_matching_for_non_null_object()
{
var obj = new object();
if (!(obj is { } instance)) // false
return;
if (instance is null) // false
throw new Exception("Never reached");
// this does not throw an exception (test passes)
}
在 C#9 中,引入了新关键字 not
,旨在将 !(x is null)
等模式简化为 x is not null
。如果我现在尝试将新的 not
关键字应用于包含 { }
的模式,我会得到一个非常令人惊讶的结果:
[Fact]
public void Csharp_9_pattern_matching_for_non_null_object()
{
var obj = new object();
if (obj is not { } instance) // false
return;
if (instance is null) // true
throw new Exception("Why the heck is this null");
// this does throw an exception (test fails)
}
即使 obj
不是 null
,instance
变量也未初始化。为了得到一个更好的,通过避免 obj
变量 instance
将被初始化:
[Fact]
public void Csharp_9_pattern_matching_for_non_null_object_without_obj_variable()
{
if (new object() is not { } instance) // false
return;
if (instance is null) // false
throw new Exception("Never reached");
// this does not throw an exception (test passes)
}
有人知道这是否是我们想要的行为吗?如果是,其背后的意图是什么?
正如 Yari Halberstadt 所指出的,这实际上是一个编译器错误。我在 Csharplang discussions 上发布了一个关于此的问题,并被告知此问题已得到解决。
正如 canton7 指出的那样,该问题最近已修复,目前尚未发布。
一旦发布,所有示例测试用例都应该通过。根据 this C#9 release blog ,失败的测试用例实际上是一个有效的用例,其中使用了以下示例:
if (e is not Customer c) { throw ... } // if this branch throws or returns...
var n = c.FirstName; // ... c is definitely assigned here