Есть ли способ восстановить кортеж в совместимый класс?
Учитывая 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)
...
}
Возможно ли это? Доступный? Планируемый? Кажется, я ничего не могу найти. Или, возможно, повторно используемый код/трюк для "Восстановления"?
Ответы
Ответ 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, которые являются краткими поскольку языковая функция не обсуждалась подробно).