有没有办法将元组重建为兼容的 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 笔记,由于语言特征没有在细节)。
给定一个元组 (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 笔记,由于语言特征没有在细节)。