I am trying to check if an object
variable is (int, int)
and if so I will use the casted variable so I have tried the codes below:
//this one gives the error
public void MyMethodWithIs(object val)
{
if(val is (int id, int name) pair)
{
ConsoleWriteLine($"{pair.id}, {pair.name}");
}
}
//This one works
public void MyMethodWithAs(object val)
{
var pair = val as (int id, int name)?;
if(pair!=null)
{
ConsoleWriteLine($"{pair.id}, {pair.name}");
}
}
The MyMethodWithIs
method gives the error below in the editor:
No suitable deconstruct instance or extension method was found for type
My Question
Why one works fine but the other gives an error at all? I think MyMethodWithIs
more readable and suitable to use for my case but I can't use it due to giving an error.
Using C# 8's pattern matching capabilities, you can write this:
if (val is (int id, int name))
{
Console.WriteLine($"id: {id}; name: {name}");
}
However this boxes id
and name
, which is surprising. There's a proposal to optimize this.
Below C# 8, you can write this:
if (val is ValueTuple<int, int> pair)
{
Console.WriteLine($"id: {pair.Item1}; name: {pair.Item2}");
}
You can of course make it a bit clearer:
if (val is ValueTuple<int, int> pair)
{
var (id, name) = pair;
Console.WriteLine($"id: {id}; name: {name}");
}
It looks like you can also deconstruct the ValueTuple inline:
if (val is ValueTuple<int, int>(var id, var name))
{
Console.WriteLine($"id: {id}; name: {name}");
}
... which is somewhat horrific, but appears to be legal.
I might have expected val is (int, int) pair)
to work, but it seems nobody's designed this case (yet).