Search code examples
c#valuetuple

Using `is` operator with value type tuples gives error


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.


Solution

  • 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).