【发布时间】:2017-10-10 18:17:38
【问题描述】:
给定一个函数(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.
类解构器的行为类似于第一种情况。给定一个类C 和Deconstructor(out string a, out string b):
var c = new C();
var (h, i) = c;
(string j, string k) = c;
但编译器不会使用解构器将其隐式转换为元组:
// 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# 团队也想到了,如果他们选择不为隐式转换添加“魔法”支持,他们有充分的理由1。
自动进行隐式转换是个坏主意,有什么积极的理由吗?
或者它是那些被认为价值不足以证明成本合理的功能之一?
这是来自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;
}
}
1 C# 团队可能并不比所有人都聪明,但我从来没有因为赌他们至少和我一样聪明而赔过钱。
【问题讨论】:
-
显然,您不希望隐式解构,就像您通常不希望从一个类隐式转换到另一个类一样。此外,从同一来源同时使用元组和解构变量也没有多大意义。它只会使代码更难理解。作为一名语言设计者,无论如何开始更严格然后最终泛化而不是相反是有意义的。例如,引用类型默认可以为空的事实是 C# 现在被认为是最大的设计错误之一......
标签: c# c#-7.0 valuetuple