сопоставление с образцом и неназначенная локальная переменная - PullRequest
1 голос
/ 16 января 2020

Я делаю:

(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);
}

Я получаю

Ошибка CS0165 Использование неназначенной локальной переменной 'name1'

в Console.WriteLine


Это работает:

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

Я пытаюсь понять почему это так? так как MyFun c () вызывается, кортеж результатов доступен, почему компилятор не назначает его и не позволяет мне его использовать?

Это был бы чрезвычайно полезный способ возврата статуса + результата, есть ли смысл запрашивать эту функцию?

Ответы [ 3 ]

7 голосов
/ 16 января 2020

name1 и name2 будут назначены, только если возвращаемое значение MyFunc() соответствует шаблону. И в этом случае метод возвращает.

Таким образом, Console.WriteLine(name1); будет выполняться, только если MyFunc() не соответствует шаблону. И в этом случае name1 и name2 не будут назначены.

Это будет работать:

void f()
{
    (var error, var name1, var name2) = MyFunc();
    if (error) return;
    Console.WriteLine(name1);
}
3 голосов
/ 16 января 2020

Обновление

Синтаксис в этом вопросе не так легко прочитать, поэтому я запутался. Деконструкция выполняется по мере необходимости, только после успешного совпадения. Этот пример Sharplab.io показывает, что это:

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

преобразуется в это в режиме выпуска:

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

Вместо попытки проверки на сбой проверьте для success и использовать переменные:

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);
2 голосов
/ 22 января 2020

ваша переменная 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();
}
...