1

I'm trying to use declaration patterns as described here: https://learn.microsoft.com/dotnet/csharp/language-reference/operators/patterns#declaration-and-type-patterns

I can see that the examples only mention using declaration patterns in if conditions, like this:

object greeting = "Hello, World!";
if (greeting is string message)
{
    Console.WriteLine(message.ToLower());  // output: hello, world!
}

Patterns do generally work outside of if conditions, i.e. anywhere you could put a Boolean expression. So I could write this:

var isString = greeting is string;

But then if I try making it a declaration pattern, I get a compiler error... not from the declaration pattern itself, but only when I try using the declared variable:

var isString = greeting is string str;

Console.WriteLine(str); // Compiler Error CS0165: Use of unassigned local variable 'str'

Intuitively, I would expect the variable str to be initialized with the value of greeting just like when I do that in an if condition. Is there a way I can get it to work?

6
  • 1
    But what would you like to happen in the 2nd case if greeting is not a string ? If you are sure it is, you can simply use a cast. Commented Jul 25, 2024 at 10:26
  • @wohlstad oh that actually explains everything. I hadn't considered the case when it's false. So that's why it only works in if conditions, because the if block only executes when it's true Commented Jul 25, 2024 at 10:32
  • Yes, that is what I meant. Commented Jul 25, 2024 at 10:33
  • I guess I'd still like to be able to use the variable somehow, but the compiler checks aren't extensive enough to allow me to use the variable inside something like if (isString) { }. If you want to post an answer explaining that this is the reason why it's impossible, I'd accept it. It's just weird that I'm allowed to declare the variable outside of an if condition in the first place. Commented Jul 25, 2024 at 10:37
  • 1
    Sure, it's perfectly fine, don't worry about it (and I agree the accepted answer is more complete). Commented Jul 25, 2024 at 13:01

3 Answers 3

2

Compare to the following (roughly equivalent) code:

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'
}

You can see that the variable str is declared in all cases, but it's only assigned a value if isString is true.

The definite assignment analysis isn't able to deduce that if isString was true for the Console.WriteLine test, it must also have been true for the case which assigns str, and that therefore str must be assigned.


Now, with the above code, you can write:

bool isString = greeting is string;
if (isString)
{
    str = (string)greeting;
}
else
{
    str = "default";
}

// str can now be used, as it is definitely assigned

You can do the same with patterns:

if (greeting is string str)
{
    // ...
}
else
{
    str = "default";
}
Sign up to request clarification or add additional context in comments.

Comments

2

You have to consider the case where greeting is not actually a string.

In the first snippet it is taken care of due to the if.
message will have the string value in greeting only if it is actually a string.

But in the second snippet the case is not handled and therefore it is a problem to allow to use the string variable you would like (str).

If you are actually sure greeting is a string, you can simply use a cast:

string str = (string)greeting;

Comments

1

Just to add that there is also the as operator

object greeting = "Hello, World!";
var str = greeting as string;
Console.WriteLine(str);

The benefit is that it doesn't throw an exception like a cast would. If the greeting wasn't of type string, then str will be set to null.

2 Comments

This is actually pretty useful for my case because you can then use str in patterns and conditions afterwards that check if it's null, which would mean greeting wasn't a string
yeah, the benefit is that you use the casted variable at top level of indentation which I thought you might be after.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.