c# - 模式匹配和范围 - If 语句
问题描述
因此,我一直在为以下代码片段绞尽脑汁,或者说缺乏大脑:
public static void Main()
{
string a = "sdasd";
object b = (object)a;
object c = (object)a;
if (b is string mystring) {
Console.WriteLine(mystring);
}
if (c is string mystring) {
Console.WriteLine(mystring);
}
}
(https://dotnetfiddle.net/tUTcOR)
尝试编译上述代码将产生编译时错误:
名为“mystring”的局部变量或函数已定义或在此范围内
我被引导相信在 if 语句的表达式中声明的任何内容的范围都与所述语句的范围相同,因此在上面的示例中,“main”将定义范围。这是有道理的。
参考 MSDN 文档:
public static double ComputeAreaModernIs(object shape)
{
if (shape is Square s)
return s.Side * s.Side;
else if (shape is Circle c)
return c.Radius * c.Radius * Math.PI;
else if (shape is Rectangle r)
return r.Height * r.Length;
// elided
throw new ArgumentException(
message: "shape is not a recognized shape",
paramName: nameof(shape));
}
让我们从范围开始详细检查这两个规则。变量 c 仅在第一个 if 语句的 else 分支的范围内。变量 s 在方法 ComputeAreaModernIs 的范围内。这是因为 if 语句的每个分支都为变量建立了一个单独的范围。但是,if 语句本身没有。这意味着在 if 语句中声明的变量与 if 语句(本例中的方法)在同一范围内。这种行为不是特定于模式匹配的,而是变量范围以及 if 和 else 语句的定义行为。
当相应的 if 语句为真时,变量 c 和 s 被赋值,因为当真时明确赋值的机制。
(https://docs.microsoft.com/en-us/dotnet/csharp/pattern-matching)
现在给出上述解释,我想注意两个具体点,并提供另一个代码片段:
这是因为 if 语句的每个分支都为变量建立了单独的范围
和
当相应的 if 语句为真时,分配变量 c 和 s
public static void Main()
{
string a = "sdasd";
object b = (object)a;
object c = (object)a;
if (b is string mystring) {
Console.WriteLine(mystring);
}else if (c is string mystringg) {
Console.WriteLine(mystringg);
}else if (c is int mystringg) {
Console.WriteLine(mystringg.ToString());
}
}
(https://dotnetfiddle.net/FFZhyl)
因此,鉴于c is string mystringg
, 和c is int mystringg
被定义在单独的范围内(根据上面提到的第一个引用),并且两者都不能评估为true
(或者),这意味着两者中只有一个将被初始化(根据上面的第二个引用),为什么上面的代码不能编译?
解决方案
注意这个部分:
这是因为 if 语句的每个分支都为变量建立了一个单独的范围。但是,if 语句本身没有。
这意味着在 if 语句中声明的变量与 if 语句(本例中的方法)在同一范围内。这种行为不是特定于模式匹配的,而是变量范围以及 if 和 else 语句的定义行为。
这意味着mystring
具有方法范围。如果您在Sharplab.io中测试代码,您会看到以下代码:
string a = "sdasd";
object b = (object)a;
object c = (object)a;
if (b is string mystring) {
Console.WriteLine(mystring);
}
if (c is string mystring1) {
Console.WriteLine(mystring1);
}
被翻译成这样:
string text = "sdasd";
object obj = text;
object obj2 = text;
string text2 = obj as string;
if (text2 != null)
{
Console.WriteLine(text2);
}
string text3 = obj2 as string;
if (text3 != null)
{
Console.WriteLine(text3);
}
推荐阅读
- html - 将 flexbox div 调整为内容的大小
- java - 创建 .jar 和 FileNotFoundException
- javascript - 如何更正此正则表达式以从报告中提取系列和图像编号?
- c# - 分析递归算法的时间复杂度
- javascript - Laravel 7 在模式(弹出)上显示正确的用户
- json - Json Spring Boot Jackson 如何反序列化具有命名空间前缀的子实体的 Json?
- html - 在线性渐变中使用图像而不是颜色
- sql - 如何调试无法更新Oracle中表列的过程?
- c# - c# Excel-VSTO 锁定解锁单元格非常慢
- python - 如何使用 Python 修改文件中的一行