Деконструировать с помощью List‹T›

Есть ли способ разрешить деконструкцию списка кортежей до List<T>?

Я получаю следующую ошибку компиляции со следующим образцом кода:

Невозможно неявно преобразовать тип «System.Collections.Generic.List‹ Deconstruct.Test>» в «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....
        }
    }
}

person rhughes    schedule 23.06.2019    source источник
comment
Нет, вы не можете использовать Value-Tuple и класс взаимозаменяемо.   -  person Tobias Tengler    schedule 23.06.2019
comment
Каков был бы желаемый результат tupleList = testList? Новый независимый список, содержащий копии элементов исходного списка, преобразованные в кортежи? Или список-оболочка, отражающий содержимое исходного списка, спроецированного как кортежи?   -  person Theodor Zoulias    schedule 23.06.2019
comment
@TheodorZoulias Идея возникла при попытке передать List<T> в метод, который принимал список кортежей в качестве аргумента.   -  person rhughes    schedule 24.06.2019
comment
@rhughes в этом случае зависит от того, должен ли метод изменять исходный List<T> или нет. Я предполагаю, что это не так, и в этом случае решения @EliahuAaron вполне достаточно.   -  person Theodor Zoulias    schedule 24.06.2019


Ответы (1)


Вам нужно явно преобразовать testList (List<Test>) в tupleList (List<(int, int)>)

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

Объяснение:

Вы используете код так, как будто Deconstruct позволяет преобразовать класс, реализующий Deconstruct, в кортеж (ValueTuple), но это не то, что делает Deconstruct.

Из документации Деконструкция кортежей и других типов:

Начиная с C# 7.0, вы можете извлекать несколько элементов из кортежа или извлекать несколько полей, свойств и вычисляемых значений из объекта в одной операции деконструкции. При деконструкции кортежа вы присваиваете его элементам отдельные переменные. При деконструкции объекта вы присваиваете выбранные значения отдельным переменным.

Деконструкция возвращает несколько элементов в отдельные переменные, а не кортеж (ValueTuple).

Попытка преобразовать List<Test> в List<(int, int)> следующим образом:

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

не может работать, потому что вы не можете преобразовать List<Test> в List<(int, int)>. Это вызовет ошибку компилятора:

Невозможно неявно преобразовать тип «System.Collections.Generic.List» в «System.Collections.Generic.List‹(int, int)>»

Попытка привести каждый элемент Test к (int, int) следующим образом:

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

не может работать, потому что вы не можете преобразовать Test в (int, int). Это вызовет ошибку времени выполнения:

System.InvalidCastException: «Указанное приведение недопустимо».

Попытка преобразовать один элемент Test в (int, int) следующим образом:

(int, int) tuple = test;

не может работать, потому что вы не можете преобразовать Test в (int, int). Это сгенерирует ошибку компилятора:

Невозможно неявно преобразовать тип "Deconstruct.Test" в "(int, int)"

person Eliahu Aaron    schedule 23.06.2019