Подтвердить что ты не робот

Есть ли способ восстановить кортеж в совместимый класс?

Учитывая tuple (int, string) v и класс C {int, string}, в С# 7, реализация C Deconstruct (out int k, out string v) позволит ff.:

C c = new C();
(int k, string v) = c;

Но обратное кажется неподдерживаемым, так что кортеж может быть "восстановлен" совместимому классу:

(int k, string v) vt = (1, "one");
C c = vt;

Я думаю, что он должен поддерживаться, если C имеет конструктор, который "соответствует" параметрам C Deconstruct():

class C
{
    public C(int k, string v)
    ...
}

Возможно ли это? Доступный? Планируемый? Кажется, я ничего не могу найти. Или, возможно, повторно используемый код/​​трюк для "Восстановления"?

4b9b3361

Ответ 1

Конечно, вы можете. Просто реализуйте неявный оператор:

public static implicit operator C((int, string) t) 
    => new C(t.Item1, t.Item2);

Нет необходимости в специальном методе Reconstruct, потому что язык уже предоставляет необходимые инструменты для достижения желаемого поведения.

Ответ 2

Существует очень тонкое различие между:

(int, string) x = c; // tuple assignment
(int a, string b) x = c; // tuple assignment with member aliases

и

(int a, string b) = c; // deconstruction

Важно, что ваш код ни один из этих, поэтому не будет компилироваться, но из контекста ясно, что вы говорите о синтаксисе деконструкции, поэтому я принимаю нижнюю форму.

Синтаксис деконструкции (один без имени после кортежного выражения) фактически не создает кортеж. На самом деле для пары требуются имена :

(int a, string b) = c;

или

var (a, b) = c;

Это не кортеж, а удобный синтаксис для:

c.Deconstruct(out int a, out string b);

Итак: ни в коем случае не задействованы кортежи (хотя, как ни странно, ссылка System.ValueTuple по-прежнему требуется).

Обратная операция - передача нескольких переменных в конструктор - это: обычный конструктор. Обратите внимание, что вы не можете передать "кортежную вещь" в любом месте, потому что у нее нет имени - это не локальный.

Ответ 3

Существует уже способ сделать противоположное деконструирование (т.е. отделить какой-то объект от его компонентов). Это "конструирование" (т.е. Создание объекта из компонентов). Самый простой способ сделать обратное (x, y) = c; - сделать c = new C(x, y);.

Существует функция-кандидат, которая рассматривается как упрощающая синтаксис типа c = new C(x, y); вплоть до c = new (x, y); путем исключения/вывода типа конструктора. Он назывался построенной по типу конструкции ([1]).

Если вы хотите предложить другой способ построения, было бы важно показать значение новой функции. csharplang repo - это хорошее место для обсуждения таких идей и общения с сообществом и отзывами команды.

Удаление new может обсуждаться, но я не думаю, что это хорошая идея. Например, в (x, y, z) = (a, b); должен ли компилятор конструировать тип C из двух элементов a и b, а затем вызвать метод Deconstruct с тремя элементами, которые он может найти на C? Вы можете видеть, как обработка деконструкций как преобразований (которые могут цепочки и появляться в ряде мест в коде) приводит к комбинаторному взрыву.

[1]: https://github.com/dotnet/csharplang/issues/100 (ссылка отслеживает эту функцию кандидата и имеет ссылку на последние заметки LDM, которые являются краткими поскольку языковая функция не обсуждалась подробно).