Я пытаюсь использовать шаблоны объявлений, как описано здесь: https://learn.microsoft.com/dotnet/csharp/language-reference/operators/patterns#declaration-and-type-patterns
Я вижу, что в примерах упоминается использование шаблонов объявлений только в условиях if, например:
object greeting = "Hello, World!";
if (greeting is string message)
{
Console.WriteLine(message.ToLower()); // output: hello, world!
}
Шаблоны обычно работают вне условий if, т. е. везде, где можно поместить логическое выражение. Поэтому я мог бы написать это:
var isString = greeting is string;
Но затем, если я попытаюсь сделать это шаблоном объявления, я получу ошибку компилятора ... не из-за самого шаблона объявления, а только тогда, когда я попытаюсь использовать объявленную переменную:
var isString = greeting is string str;
Console.WriteLine(str); // Compiler Error CS0165: Use of unassigned local variable 'str'
Интуитивно я ожидал, что переменная str
будет инициализирована значением greeting
точно так же, как когда я делаю это в условии if. Есть ли способ заставить его работать?
@wohlstad о, это на самом деле все объясняет. Я не учел тот случай, когда оно неверно. Вот почему он работает только в условиях if, потому что блок if выполняется только тогда, когда он истинен.
Да, это то, что я имел в виду.
Думаю, мне все равно хотелось бы каким-то образом использовать эту переменную, но проверки компилятора недостаточно обширны, чтобы позволить мне использовать переменную внутри чего-то вроде if (isString) { }
. Если вы хотите опубликовать ответ, объясняющий, что это причина, по которой это невозможно, я бы принял это. Просто странно, что мне разрешено объявлять переменную вне условия if.
@wohlstad Извините за ложное обещание. Со стороны canton7 мне показалось несправедливым принимать чужой ответ только потому, что я не обращал достаточно внимания, чтобы заметить его ответ, пока разговаривал с вами.
Конечно, все в порядке, не беспокойтесь об этом (и я согласен, что принятый ответ более полный).
Сравните со следующим (примерно эквивалентным) кодом:
object? greeting = "test";
string str;
bool isString = greeting is string;
if (isString)
{
str = (string)greeting;
}
if (isString)
{
Console.WriteLine(str);
// error CS0165: Use of unassigned local variable 'str'
}
Вы можете видеть, что переменная str
объявлена во всех случаях, но ей присваивается значение только в том случае, если isString
равно true
.
Анализ определенного присваивания не позволяет сделать вывод, что если isString
было true
для теста Console.WriteLine
, то оно также должно было быть true
и для случая, который присваивает str
, и, следовательно, str
должно быть присвоено.
Теперь с помощью приведенного выше кода вы можете написать:
bool isString = greeting is string;
if (isString)
{
str = (string)greeting;
}
else
{
str = "default";
}
// str can now be used, as it is definitely assigned
То же самое можно сделать и с узорами:
if (greeting is string str)
{
// ...
}
else
{
str = "default";
}
Вам следует рассмотреть случай, когда greeting
на самом деле не является string
.
В первом фрагменте об этом позаботятся благодаря if
.message
будет иметь значение string
в greeting
, только если это на самом деле string
.
Но во втором фрагменте случай не обрабатывается, и поэтому проблематично разрешить использование нужной строковой переменной (str
).
Если вы действительно уверены, что greeting
— это string
, вы можете просто использовать приведение типов:
string str = (string)greeting;
Просто добавим, что есть еще оператор as
.
object greeting = "Hello, World!";
var str = greeting as string;
Console.WriteLine(str);
Преимущество в том, что он не генерирует исключение, как это было бы приведение типов. Если приветствие не типа string
, то str
будет установлено на null
.
На самом деле это очень полезно для моего случая, потому что потом вы можете использовать str
в шаблонах и условиях, которые проверят, является ли он нулевым, что будет означать, что greeting
не является строкой.
да, преимущество в том, что вы используете приведенную переменную на верхнем уровне отступа, что, как я думал, вам может понадобиться.
Но что бы вы хотели, чтобы произошло во втором случае, если
greeting
не являетсяstring
? Если вы уверены, что это так, вы можете просто использовать приведение типов.