Deconstruct with List<T>
Asked Answered
P

1

6

Is there a way to allow a list of tuples to deconstruct to a List<T>?

I get the following compile error with the following code sample:

Cannot implicitly convert type 'System.Collections.Generic.List< Deconstruct.Test>' to 'System.Collections.Generic.List<(int, int)>'

using System;
using System.Collections.Generic;

namespace Deconstruct
{
    class Test
    {
        public int A { get; set; } = 0;

        public int B { get; set; } = 0;

        public void Deconstruct(out int a, out int b)
        {
            a = this.A;
            b = this.B;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var test = new Test();

            var (a, b) = test;

            var testList = new List<Test>();

            var tupleList = new List<(int, int)>();

            tupleList = testList; // ERROR HERE....
        }
    }
}
Postpaid answered 23/6, 2019 at 11:13 Comment(4)
No, you can't use a Value-Tuple and a class interchangeably.Heaviside
What would be the desired outcome of tupleList = testList? A new independent list containing copies of the original list's elements, converted to tuples? Or a wrapper list reflecting the contents of the original list, projected as tuples?Turret
@TheodorZoulias The idea came about when trying to pass a List<T> into a method which accepted a list of tuples as an argument.Postpaid
@Postpaid in this case it depends on whether the method is supposed to modify the original List<T> or not. I guess that it doesn't, in which case @EliahuAaron's solution is completely sufficient.Turret
B
10

You need to explicitly convert the testList (List<Test>) to tupleList (List<(int, int)>)

tupleList = testList.Select(t => (t.A, t.B)).ToList();

Explanation:

Your are using the code as if the Deconstruct lets you convert a class implementing Deconstruct to a tuple (ValueTuple), but that's not what Deconstruct dose.

From documentation Deconstructing tuples and other types:

Starting with C# 7.0, you can retrieve multiple elements from a tuple or retrieve multiple field, property, and computed values from an object in a single deconstruct operation. When you deconstruct a tuple, you assign its elements to individual variables. When you deconstruct an object, you assign selected values to individual variables.

Deconstruction returns multiple elements to individual variables, not a tuple (ValueTuple).

Attempting to convert a List<Test> to a List<(int, int)> like this:

var testList = new List<Test>();
var tupleList = new List<(int, int)>();
tupleList = testList;

cannot work because you cannot convert a List<Test> to a List<(int, int)>. It will generate a compiler error:

Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List<(int, int)>'

Attempting to cast each Test element to a (int, int) like this:

tupleList = testList.Cast<(int, int)>().ToList();

cannot work because you cannot cast a Test to a (int, int). It will generate a run-time error:

System.InvalidCastException: 'Specified cast is not valid.'

Attempting to convert a single Test element to a (int, int) like this:

(int, int) tuple = test;

cannot work because you cannot convert a Test to a (int, int). It will generates a compiler error:

Cannot implicitly convert type 'Deconstruct.Test' to '(int, int)'

Bors answered 23/6, 2019 at 11:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.