有没有办法将元组重建为兼容的 class?

Is there a way to reconstruct a tuple to a compatible class?

给定一个元组 (int, string) v 和一个 class C { int, string },在 C#7 中,实现 C 的 Deconstruct(out int k, out string v) 将允许 ff。 :

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

但反过来似乎不受支持,这样元组可以 "reconstructed" 到兼容的 class:

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

我认为如果 C 具有 "matches" C 的 Deconstruct() 参数的构造函数,则应该支持它:

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

可能吗?可用的?计划?我似乎找不到任何相关信息。或者也许是可重复使用的 code/trick 到 "Reconstruct"?

当然可以。只需实现一个隐式运算符:

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

不需要一些特殊的Reconstruct方法,因为语言已经提供了必要的工具来实现你想要的行为。

有一个非常微妙的区别:

(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 引用仍然是必需的)。

反向操作 - 将多个变量传递给构造函数 - 是:常规构造函数。请注意,您不能在任何地方传递 "tuple-like thing" ,因为 它没有名称 - 它不是本地的 .

已经有一种方法可以进行与解构相反的操作(即,将一些对象分解为其组成元素)。它是 "constructing"(即从组件创建对象)。与 (x, y) = c; 相反的最直接的方法是 c = new C(x, y);.

有一个候选功能被考虑通过 omitting/inferring 构造函数的类型将 c = new C(x, y); 等语法简化为 c = new (x, y);。它称为目标类型构造 ([1])。

如果你想提出一些其他的构建方式,那么展示新功能的价值很重要。 csharplang repo 是讨论此类想法并感受社区和团队反馈的好地方。

可以讨论删除 new,但我认为这不是一个好主意。例如,在 (x, y, z) = (a, b); 中,编译器是否应该考虑从两个元素 a 和 b 构造一个类型 C,然后使用可能在 C 上找到的三个元素调用 Deconstruct 方法?您可以看到将解构视为转换(可以链接并出现在代码中的许多地方)如何导致组合爆炸。

[1]: https://github.com/dotnet/csharplang/issues/100(link 跟踪这个候选特征并且有一个 link 到最近的 LDM 笔记,由于语言特征没有在细节)。