模式匹配和未分配的局部变量

pattern matching and unassigned local variable

我愿意:

(bool success, string name1, string name2) MyFunc() {
  if (DateTime.Now.Year > 2020) return (false, "", ""); // error 
  return (true, "some value", "some value");
}

我的编码风格是先尝试处理错误,我尝试过:

void f() {
  if (MyFunc() is (false, var name1, var name2)) return;
  Console.WriteLine(name1);
}

我明白了

Error CS0165 Use of unassigned local variable 'name1'

Console.WriteLine


这有效:

void f() {
  if (!(MyFunc() is (true, var name1, var name2)))) return;
  Console.WriteLine(name1);
}

我想了解为什么会这样?既然调用了MyFunc(),结果元组是可用的,为什么编译器不分配它让我使用它?

这本来是一种非常有用的返回状态+结果的方式,请求该功能是否有意义?

name1name2 仅当 return 值 MyFunc() 与模式匹配时才会分配。并且,在那种情况下,方法 returns.

因此,Console.WriteLine(name1); 只有在 MyFunc() 不匹配模式时才会执行。并且,在这种情况下,name1name2 将不会被分配。

这会起作用:

void f()
{
    (var error, var name1, var name2) = MyFunc();
    if (error) return;
    Console.WriteLine(name1);
}

更新

这个问题的语法不太好读,所以我很困惑。仅在匹配成功后才根据需要执行解构。这 Sharplab.io example 表明这 :

void f() {
  if (MyFunc() is (false, var name1, var name2)) {
        Console.WriteLine(name1);
        return;
   }
}

在Release模式下转换成这样:

private void f()
{
    ValueTuple<bool, string, string> valueTuple = MyFunc();
    if (!valueTuple.Item1)
    {
        string item = valueTuple.Item2;
        Console.WriteLine(item);
    }
}

与其尝试检查失败,不如检查成功并使用变量:

void f() {
  if (MyFunc() is (true, var name1, var name2)) {
      Console.WriteLine(name1);
  }
}

或者通过在块外使用变量来扩大范围:

var (success,name1,name2)= MyFunc();
if (!success) return;
Console.WriteLine(name1);

或者使用 switch 语句:

switch(MyFunc()) {
    case (false, _,):
        return ;
    case (success, var name1,var name2):
        Console.WriteLine(name1);        
        break;
}

您还可以定义单独的变量并利用赋值是表达式这一事实,但这变得很丑陋:

bool success;
string name1;
string name2; 

if ( ((success,name1,name2)=MyFunc()) is (false,_,_)) {
    return;
}

Console.WriteLine(name1);

你的 bool 变量没有被实例化,而字符串有。

试试这个:

static (bool success, string name1, string name2) MyFunc()
{
    if (DateTime.Now.Year > 2020) return (false, "", "");
        return (true, "some value", "some value");
}

static void f()
{
    if (MyFunc() is var (b, name1,name2) && !b) return;
        Console.WriteLine(name1);
}

public static void Main()
{
    f();
}