C# 有没有办法将元组重构为兼容类?

C# 有没有办法将元组重构为兼容类?,c#,.net,c#-7.0,C#,.net,C# 7.0,给定一个元组(int,string)v和一个类C{int,string},在C#7中,实现C的解构(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 {

给定一个元组(int,string)v和一个类C{int,string},在C#7中,实现C的解构(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)
    ...
}

可能吗?有空吗?计划?我似乎找不到关于它的任何东西。或者是一个可重用的代码/技巧来“重建”?

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

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

不需要一些特殊的重构方法,因为该语言已经提供了实现所需行为的必要工具。

以下两者之间有一个非常微妙的区别:

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

重要的是,您的代码既不是这两个,也不是这两个,因此不会编译-但从上下文来看,很明显,您在谈论解构语法,因此我假设是底部形式

解构语法(类似元组的表达式后面没有名称的)实际上并不创建元组。事实上,它需要一对中的名称

(int a, string b) = c;
或:

这不是一个元组,而是一种方便的语法:

c.Deconstruct(out int a, out string b);
因此:在任何时候都不涉及元组(尽管奇怪的是,
系统.ValueTuple
引用仍然是必需的)


反向操作(将多个变量传递给构造函数)是:常规构造函数。请注意,您不能将“类似元组的东西”传递到任何地方,因为它没有名称-它不是本地的。

已经有了一种与解构相反的方法(即将某个对象分解为其组件元素)。它是“构造”(即从组件制作对象)。与
(x,y)=c相反的最直接的方法是做
c=新的c(x,y)

有一个候选特性正在考虑简化语法,比如
c=newc(x,y)向下至
c=新(x,y)通过省略/推断构造函数的类型。它被称为目标类型构造([1])

如果你想提出一些其他的构造方法,那么展示新特性的价值是很重要的。这是一个讨论这些想法、了解社区和团队反馈的好地方

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


[1] :(该链接跟踪此候选功能,并有一个指向最新LDM注释的链接,这些注释非常简洁,因为没有详细讨论语言功能)

这看起来像是“鸭子打字”,他们不支持,因为自由带来的问题很多。有可能在C#7中发生了变化,不过我会感到惊讶。我认为没有这样的功能,我怀疑它是否有用。如果一个类有2个int和3个string属性呢。您需要多久使用一次此功能?为什么不能使用可读且安全的方法:
cc=newc{IntPropName=tuple.Item1,StringPropName=tuple.Item2}?解构是否使用元组?当然,它使用类似元组的语法,但是:那里没有元组。。。它解构为变量(这些变量需要名称-问题顶部的代码不可编译-需要是
(int a,string b)
IIRC),这表明属性是公共的。如果C的k和v只能通过C的构造函数来计算,那么如果“重建”总是通过C的构造例程,则可能还可以。@krillgar它不会是“duck typing”,因为仍然需要在
C
中实现此行为(与
disconstruct
相同);只要类型结构兼容,它就不是应该工作的默认行为。所需的行为可以通过隐式运算符轻松实现。隐式运算符限制为2个值/属性。“泛型”重构(与Deconstruct()相反)可能需要语言/编译器级别的支持。不过,克里尔加称之为“鸭子打字”。@EdmundoMendiola我没听清楚。您还需要实现
解构
,它不内置于任何
值元组
。唯一的编译器支持是一个方便的语法,它在相反的方向上是不需要的,因为您确实在处理一个元组和一个编译器完全理解的很好的旧隐式转换。@Edmundiola我的“duck typing”注释主要是在您的第一个“嗯,它应该能工作,因为我可以看到它走路像
C
,说话像
C
。作为一个人,我知道这是一个
C
“中间的代码显示了你可以做你想做的事情,但是你期望发生的事情并没有自然地融入到语言中,尽管它们为你提供了在特定情况下做事情的工具。这是一个完全通用的解决方案(我假设使用类似于
params
)的东西可能不可用,但我将遵循中间的方法。是的。正如我的问题中所述,C必须实现Deconstruct()。如果我没听错,如果我想“重建”“,那么我也应该为C实现一个隐式运算符。我在想,只要C有一个与解构()交互的构造函数,重构是否可以像语言/语法的一部分一样“自动”进行。它是为解构()完成的,所以…@EdmundoMendiola不,没有,也不方便;你怎么看
var (a, b) = c;
c.Deconstruct(out int a, out string b);