2017-05-11 25 views
8

Fiddle hereC#7值元组/解构不对称

给出一个函数(string a, string b) F(),可以解构它返回的元组:

var (a, b) = F(); 

(string c, string d) = F(); 

或者你可以给它分配:

var (a, b) e = F(); 

(string a, string b) f = F(); 

var g = F(); // One of these things is not like the others. 

类deconstructors行为类似于第一种情况。鉴于一类CDeconstructor(out string a, out string b)

但是,编译器将不使用解构隐含地将其转换为一个元组:

// Cannot implicitly convert type 'C' to '(string a, string b)' 
var (a, b) l = c; 

很明显,你可以写机械基础上,解构的隐式转换:

public static implicit operator (string a, string b) (C c) 
{ 
    c.Deconstruct(out string a, out string b); 
    return (a, b); 
} 

尽管解构和赋值情况之间的语法在视觉上相似,但与签署对元组的引用与将类解构成变量并将它们放入新元组不同。但是,您可以将(int x, int y)隐式转换为(double x, double y)。值元组是语法糖的一种特征,它看起来就像它一样,并且不用介意实现细节。

如果我想到了这一点,C#团队想到了这一点,如果他们选择不为隐式转换添加“魔术”支持,他们有一个很好的理由。

有一个积极的原因,为什么自动执行隐式转换会是一个坏主意?

或者它是那些被认为不足以证明成本的特征之一?


下面的代码从that fiddle

public class Program 
{ 
    public static void Main() 
    { 
     (string a, string b) = F(); 

     (string a, string b) ab = F(); 

     Console.WriteLine($"a: {a} b: {b} ab: {ab}"); 


     var c = new C(); 

     (string d, string e) = c; 

     // Cannot implicitly convert type 'C' to '(string a, string b)' 
     (string a, string b) f = c; 

     Console.WriteLine($"d: {d} e: {e} f: {f}"); 

     // Covariance 
     (object c, object d) g = F(); 
     // Implicit conversion 
     (double x, double y) t = G(); 
    } 

    public static (string a, string b) F() 
     => ("A", "B"); 

    public static (int x, int y) G() 
     => (0, 1); 
} 

public class C 
{ 
    public String A = "A"; 
    public String B = "B"; 

    public void Deconstruct(out String a, out String b) 
    { 
     a = A; 
     b = B; 
    } 
} 

C#团队可能不会比其他人更聪明,但我从来没有赔了钱打赌,他们至少和我一样聪明。

+0

很明显,你不希望隐式解构就像你通常不希望从一个类到另一个类的隐式转换一样。而且,使用来自同一个源的元组和解构变量没有多大意义。它只会使代码更难理解。作为一个语言设计者,无论如何开始更严格,然后最终泛化,而不是相反。例如,参考类型默认为可空的事实是C#现在被认为是最大的设计错误之一... – Phil1970

回答

5

解构的能力像隐式转换器那样在C#7发布之前就被要求了(由我,所以我偏向这里)。这个团队的反应是(正如我读过的那样),它被要求离C#7版本太近,并且要花太长时间才能实现,所以不值得考虑。因为它现在将是一个突破性的改变,它不会发生。

有关此事的实际讨论,请参阅“Allow Deconstruct and implicit operator to both support deconstruction and conversion to tuple types”roslyn回购问题。

5

(string a, string b) ab声明了一个名为ab元组类型(string a, string b)变量。这可以让你编写ab.aab.b,但不是ab

(string a, string b) f = c;试图将不相关的C类型转换为此元组类型。除非你写演员,否则没有办法发生。

具体来说,顾名思义,解构只允许您分配变量;它不会让你转换成不相关的类型。

3

这里有一种方法可以实现你要做的事情:在你的代码示例中,代替(string a, string b) f = c;,使用(string a, string b) f = (_, _) = c;

您也可以编写用户定义的类型转换为您需要的元组类型。

+0

我真的很佩服这里的诀窍!我永远不想在生产代码中看到它,但它很整洁:) –