c#多任务

int a, b, n; ... (a, b) = (2, 3); // 'a' is now 2 and 'b' is now 3 

这种事情在C#中真的很有帮助。 在这个例子中,’a’和’b’没有被封装在一起,例如位置的X和Y可能是。 这是否以某种forms存在?

下面是一个不太重要的例子。

 (a, b) = n == 4 ? (2, 3) : (3, n % 2 == 0 ? 1 : 2); 

Adam Maras在评论中表示:

 var result = n == 4 ? Tuple.Create(2, 3) : Tuple.Create(3, n % 2 == 0 ? 1 : 2); 

然而,当他指出它创建一个新的三元组而不是更改指定的值时,上述示例的工作类型。

Eric Lippert要求用例,因此可能:

 (a, b, c) = (c, a, b); // swap or reorder on one line (x, y) = move((x, y), dist, heading); byte (a, b, c, d, e) = (5, 4, 1, 3, 2); graphics.(PreferredBackBufferWidth, PreferredBackBufferHeight) = 400; 

notallama也有用例,他们在下面给出了答案。

我们已经考虑过支持元组的语法糖,但它没有成为C#4.0的标准。 它不太可能成为C#5.0的标准; C#5.0团队非常忙于让异步/等待正常工作。 我们将考虑该语言的假设未来版本。

如果您有一个非常可靠的用例,这将有助于我们确定该function的优先级。

用例:

使用IObservables非常好,因为它们只有一个类型参数。 你基本上想要使用任意委托订阅,但是你被迫使用Action,这意味着如果你想要多个参数,你必须使用元组,或者创建自定义类来打包和解包参数。

来自游戏的例子:

 public IObservable> Damaged ... void RegisterHitEffects() { (from damaged in Damaged where damaged.Item2.amount > threshold select damaged.Item1) .Subscribe(DoParticleEffect) .AddToDisposables(); } 

变为:

 void RegisterHitEffects() { (from (gameObject, damage) in Damaged where damage.amount > threshold select gameObject) .Subscribe(DoParticleEffect) .AddToDisposables(); } 

我觉得它更清洁。

另外,当您想要传递多个值时,可能IAsyncResult会有类似的问题。 有时创建类只是为了改变一些数据是很麻烦的,但是现在使用元组会降低代码的清晰度。 如果它们在同一个函数中使用,那么匿名类型很适合该法案,但是如果你需要在函数之间传递数据它们就不起作用。

此外,如果糖也适用于通用参数,那就太好了。 所以:

 IEnumerator<(int, int)> 

会不会去的

 IEnumerator> 

您正在寻找的行为可以在具有元组支持或语法糖的语言中找到。 C#不属于这些语言之中; 虽然你可以使用Tuple<...>类来实现类似的行为,但它会变得非常冗长(不像你正在寻找的那样干净。)

我能想到的最接近的结构是框架版本4.0中的Tuple类。

正如其他人已经写过的那样,C#4元组是一个很好的补充,但只要没有任何解包机制,没有什么真正令人信服的。 对于我使用的任何类型,我真正要求的是它所描述的内容的清晰度,在function协议的两侧(例如来电者,主叫方)……

 Complex SolvePQ(double p, double q) { ... return new Complex(real, imag); } ... var solution = SolvePQ(...); Console.WriteLine("{0} + {1}i", solution.Real, solution.Imaginary); 

这在呼叫者和被呼叫者方面都是显而易见的。 不过这个

 Tuple SolvePQ(double p, double q) { ... return Tuple.Create(real, imag); } ... var solution = SolvePQ(...); Console.WriteLine("{0} + {1}i", solution.Item1, solution.Item2); 

不会在调用站点上留下关于该解决方案实际上是什么的确切线索(好吧,字符串和方法名称使其非常明显)。 Item1和Item2属于同一类型,这使得工具提示无效。 唯一可以确定的方法是通过SolvePQ “反向工程”。

很明显,这是遥不可及的,每个人都在做一些重要的数字应该有一个复杂的类型(就像在BCL中那样)。 但是每次你得到拆分结果并且你想为了可读性而给那些结果带来不同的名字,你需要元组解包。 重写的最后两行是:

 var (real, imaginary) = SolvePQ(...); // or var real, imaginary = SolvePQ(...); Console.WriteLine("{0} + {1}i", real, imaginary); 

除了习惯语法之外,这没有留下混淆的余地。

创建一组Unpack(this Tuple, out T1, out T2)方法将是一种更为惯用的c#方式。

那么你的榜样就会成为

 int a, b, n; ... Tuple.Create(2, 3).Unpack(out a, out b); // 'a' is now 2 and 'b' is now 3 

这并不比你的建议复杂,而且更加清晰。

在C#7.0中引入了解构: https : //blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/#user-content-deconstruction