Получение «Использование неназначенной локальной переменной» в шаблоне списка с переменной с .NET 7

Я тестировал шаблоны списков в .NET 7 и C#. Я использую Linqpad 7 и .NET 7.0.1. Шаблоны списков, я думаю, полезны для сравнения последовательностей и их интересно тестировать. Отбрасывание '_' здесь означает игнорирование числа в заданной позиции, а диапазон '..' здесь соответствует чему-либо между заданным набором значений и одним индексом, а затем заданным значением в более высоком индексе с произвольными значениями между ними.

Но в одном из примеров говорится, что вы можете захватывать переменные внутри шаблонов списков. Я не могу заставить его работать, я получаю ошибку компилятора.

Я получаю сообщение об ошибке CS0165 «Использование неназначенной локальной переменной», когда пытаюсь получить доступ к захваченным переменным. Я попытался проверить код сбоя также внутри VsCode, все еще получая ошибку, однако, если я отлаживаю внутри Linqpad, я вижу, что захваченные переменные получили значения, по крайней мере.

    var someOddNumbers = new int[] { 1, 3, 5, 7, 9, 11 };
    bool resultX = someOddNumbers is [1, 3, _, _, _, 11];
    resultX.Dump("The 'someOddNumbers' equals a sequence of numbers 1,3,then three arbitrary numbers, then 11?");

    bool isOdd = someOddNumbers is [1, .., 9, 11];
    isOdd.Dump("The 'someOddNumbers' equals a sequence of numbers 1, some arbitrary numbers, then ending with 9 and 11?");
    
    result = input is [var firstOddNumber,.. , var lastOddNumber];

    if (result)
    {
        Console.WriteLine($"The captured variables are: {firstOddNumber} and {lastOddNumber}"); //this lines gives the CS0165 error
    }

Если я закомментирую блок if, я смогу запустить пример кода, и в отладчике я увижу, что firstOddNumber и lastOddNumber устанавливаются в значение во время выполнения. Но компилятор C# 11, похоже, считает, что это недопустимый код, поскольку он использует неинициализированную переменную.

Я ожидал, что не получу ошибку компилятора и смогу также захватить переменные, определенные в шаблоне списка. Я не могу понять использование таких переменных, если я не могу их использовать. Я понимаю, что эти переменные могут быть не захвачены, если шаблон списка не совпадает, но даже при проверке наличия совпадения я получил ошибку компиляции. Однако я могу запустить код, просто не обращаясь к переменным.

Обновлять: Запятая отсутствовала перед lastOddNumber, как упомянул Гуру Строн из моего кода. И использование шаблона списка внутри условия if заставило код работать.

var someOddNumbers = new int[] { 1, 3, 5, 7, 9, 11 };
bool resultX = someOddNumbers is [1, 3, _, _, _, 11];
resultX.Dump("The 'someOddNumbers' equals a sequence of numbers 1,3,then three arbitrary numbers, then 11?");

bool isOdd = someOddNumbers is [1, .., 9, 11];
isOdd.Dump("The 'someOddNumbers' equals a sequence of numbers 1, some arbitrary numbers, then ending with 9 and 11?");

if (someOddNumbers is [var firstOddNumber, .. ,  var lastOddNumber]){   
    Console.WriteLine($"The captured variables are: {firstOddNumber} and {lastOddNumber}");
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Кажется, что компилятор на данный момент недостаточно умен, чтобы определить, что result является результатом совпадения и не изменяется (или существует много крайних случаев для реализации такой проверки). Встраивание переменной должно привести к компиляции кода:

if (input is [var firstOddNumber,.. var lastOddNumber])
{
    Console.WriteLine($"The captured variables are: {firstOddNumber} and {lastOddNumber}"); 
}

Небольшое примечание:

.. var lastOddNumber соответствует остальной части массива, а не последнему элементу, возможно, вы искали is [var firstOddNumber, .., var lastOddNumber] (т.е. добавьте запятую после ..).

УПД

Такое же поведение можно найти при «обычном» сопоставлении с образцом:

string? message = "This is not the null string";

if (message is {} m)
{
    Console.WriteLine(m); // compiles
}

var test = message is {} m1;
if (test)
{
   Console.WriteLine(m1); // error CS0165: Use of unassigned local variable 'm1'
}

На самом деле это известная проблема, заключающаяся в том, что компилятор не распространяет определенное состояние присваивания - см. это и/или это.

Демо .

Избегание использования логического флага, но использование его непосредственно внутри предложения if заставило его скомпилироваться. if (someOddNumbers is [var firstOddNumber, .. , var lastOddNumber]){ Console.WriteLine($"Захваченные переменные: {firstOddNumber} и {lastOddNumber}"); }

Tore Aurstad 09.01.2023 01:17

Другие вопросы по теме