我有两个带有Deconstruct()方法的结构(点和大小)。两者都返回(int,int)元组。
我正在尝试将它们解构为switch中的(int,int)元组变量,但没有成功。编译器给我错误:
无法将类型'Size'隐式转换为'(int,int)'。
如何将这两个结构都解构为一个元组,以便能够在第二个switch表达式中使用它?
using System;
class Program
{
static string DescribeSize<TDeconstructable>(TDeconstructable deconstructableStruct)
where TDeconstructable : struct
{
(int, int) xy;
switch (deconstructableStruct)
{
case Size size:
xy = size; //CS0029 error: Cannot implicitly convert type 'Size' to '(int, int)'
break;
case Point point:
xy = point; //CS0029 error: Cannot implicitly convert type 'Point' to '(int, int)'
break;
default:
xy = (0, 0);
break;
}
return xy switch
{
(0, 0) => "Empty",
(0, _) => "Extremely narrow",
(_, 0) => "Extremely wide",
_ => "Normal"
};
}
static void Main(string[] args)
{
var size = new Size(4, 0);
var point = new Point(0, 7);
Console.WriteLine(DescribeSize(size));
Console.WriteLine(DescribeSize(point));
}
}
public struct Point
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y)
{
X = x;
Y = y;
}
public void Deconstruct(out int x, out int y)
{
x = X;
y = Y;
}
}
public readonly struct Size
{
public int W { get; }
public int H { get; }
public Size(int w, int h)
{
W = w;
H = h;
}
public void Deconstruct(out int w, out int h)
{
w = W;
h = H;
}
}
没有对ValueTuple
的隐式转换,您的分配没有调用解构。您需要两个变量,而不是一个。如果您认为解构只是调用Deconstruct
方法的编译器技巧,这将变得更加明显。如果要手动调用它,则需要将two变量作为out
参数而不是一个参数传递。
size.Deconstruct(out x, out y);
不存在需要single元组的重载。那将如何工作?只有一个变量。我想您可能会认为编译器可以做一些类似于:
size.Deconstruct(out xy.Item1, out xy.Item2);
不幸的是,没有。对于您的情况,您需要分别声明变量(而不是将其声明为ValueTuple
),然后使用解构方法将其分配给它们。
int x, y;
...
(x, y) = size;
以后您仍然可以打开值,只需要使用元组语法:
return (x, y) switch {
(0, 0) => "Empty",
(0, _) => "Extremely narrow",
(_, 0) => "Extremely wide",
_ => "Normal"
};
您可以在结构内部添加此帮助程序方法,以根据需要返回ValueTuple。
public ValueTuple<int, int> GetValueTuple()
{
return (X, Y);
}
然后在像这样的切换情况下调用该方法。
case Size size:
xy = size.GetValueTuple();
break;
case Point point:
xy = point.GetValueTuple();
break;
您的代码示例太复杂了。该问题与通用方法或switch
无关。以下内容足以重现该问题:
var size = new Size(4, 0);
(int, int) xy;
xy = size;
This answer特别说明了为什么此语法无法工作。当然,这实际上归结为语法错误。您只是没有正确编写代码。如果您真的不需要将局部变量设为元组类型,则可以使用该答案。
也就是说,如果能够更改Point
和Size
类型,也可以使用元组类型变量来实现所需的功能。您可以简单地提供错误消息说明当前不存在的隐式转换。例如,您可以将以下内容添加到Size
类型:
public static implicit operator (int x, int y)(Size size)
{
return (size.W, size.H);
}
然后,该分配将随您想在任何地方工作,而不仅限于switch
语句。