无法将可解构类型隐式转换为元组
Cannot implicitly convert deconstructable type to Tuple
我有两个使用 Deconstruct() 方法的结构(Point 和 Size)。两者都是 return (int, int) 元组。
我试图在 switch 中将它们解构为 (int, int) 元组变量,但没有成功。编译器给我错误:
Cannot implicitly convert type 'Size' to '(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;
}
}
如果需要,您可以将此辅助方法添加到结构中 return ValueTuple。
public ValueTuple<int, int> GetValueTuple()
{
return (X, Y);
}
然后像这样在 switch case 中调用方法。
case Size size:
xy = size.GetValueTuple();
break;
case Point point:
xy = point.GetValueTuple();
break;
没有到 ValueTuple
的隐式转换,并且您的赋值没有调用解构。您实质上是在尝试执行以下不合法的操作:
xy = (ValueTuple<int, int>)size;
您需要两个变量,而不是一个。如果您认为解构只是调用 Deconstruct
方法的编译器 trickery/syntactic 糖,这一点就更明显了。如果你打算手动调用它,你需要传递两个变量作为out
参数,而不是一个。
int x, y;
size.Deconstruct(out x, out y);
没有采用 单个 元组的重载。那将如何工作?只有一个变量。我想您可能认为编译器 可以 做一些类似于:
size.Deconstruct(out xy.Item1, out xy.Item2);
不幸的是它没有。对于您的情况,您需要单独声明变量(而不是 ValueTuple
),然后使用解构和元组语法来分配给它们。如果您愿意,可以将 default
案例中的赋值移出 switch
,以使两个变量的声明具有更多元组的感觉:
var (x, y) = (0, 0); // two variables
switch (deconstructableStruct)
{
case Size size:
(x, y) = size;
break;
case Point point:
(x, y) = point;
break;
}
你以后仍然可以打开值,你只需要使用元组语法:
return (x, y) switch {
(0, 0) => "Empty",
(0, _) => "Extremely narrow",
(_, 0) => "Extremely wide",
_ => "Normal"
};
请参阅 以获得更好的选择:如果您 确实 需要一个元组类型的变量,请编写您自己的 implicit
转换运算符它拥有(并且你们都能够并且不介意修改 Size
和 Point
类型以添加此行为)。
您的代码示例太复杂了。该问题与通用方法或 switch
无关。以下足以重现问题:
var size = new Size(4, 0);
(int, int) xy;
xy = size;
具体解释了为什么这种语法不起作用。当然,这实际上只是归结为语法错误。您只是没有正确编写代码。如果您真的不需要局部变量是元组类型,那么该答案提供了一个很好的选择。
也就是说,如果您能够更改 Point
和 Size
类型,也可以使用元组类型变量实现您想要的。您可以简单地提供错误消息解释的当前不存在的隐式转换。例如,您可以将以下内容添加到 Size
类型:
public static implicit operator (int x, int y)(Size size)
{
return (size.W, size.H);
}
那么赋值就会随心所欲地在任何地方工作,而不仅仅是在 switch
语句中。
您可以从每种类型的部分创建一个元组:
case Size size:
xy = (size.Length, size.Height);
break;
case Point point:
xy = (point.X, point. Y);
break;
我有两个使用 Deconstruct() 方法的结构(Point 和 Size)。两者都是 return (int, int) 元组。
我试图在 switch 中将它们解构为 (int, int) 元组变量,但没有成功。编译器给我错误:
Cannot implicitly convert type 'Size' to '(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;
}
}
如果需要,您可以将此辅助方法添加到结构中 return ValueTuple。
public ValueTuple<int, int> GetValueTuple()
{
return (X, Y);
}
然后像这样在 switch case 中调用方法。
case Size size:
xy = size.GetValueTuple();
break;
case Point point:
xy = point.GetValueTuple();
break;
没有到 ValueTuple
的隐式转换,并且您的赋值没有调用解构。您实质上是在尝试执行以下不合法的操作:
xy = (ValueTuple<int, int>)size;
您需要两个变量,而不是一个。如果您认为解构只是调用 Deconstruct
方法的编译器 trickery/syntactic 糖,这一点就更明显了。如果你打算手动调用它,你需要传递两个变量作为out
参数,而不是一个。
int x, y;
size.Deconstruct(out x, out y);
没有采用 单个 元组的重载。那将如何工作?只有一个变量。我想您可能认为编译器 可以 做一些类似于:
size.Deconstruct(out xy.Item1, out xy.Item2);
不幸的是它没有。对于您的情况,您需要单独声明变量(而不是 ValueTuple
),然后使用解构和元组语法来分配给它们。如果您愿意,可以将 default
案例中的赋值移出 switch
,以使两个变量的声明具有更多元组的感觉:
var (x, y) = (0, 0); // two variables
switch (deconstructableStruct)
{
case Size size:
(x, y) = size;
break;
case Point point:
(x, y) = point;
break;
}
你以后仍然可以打开值,你只需要使用元组语法:
return (x, y) switch {
(0, 0) => "Empty",
(0, _) => "Extremely narrow",
(_, 0) => "Extremely wide",
_ => "Normal"
};
请参阅 implicit
转换运算符它拥有(并且你们都能够并且不介意修改 Size
和 Point
类型以添加此行为)。
您的代码示例太复杂了。该问题与通用方法或 switch
无关。以下足以重现问题:
var size = new Size(4, 0);
(int, int) xy;
xy = size;
也就是说,如果您能够更改 Point
和 Size
类型,也可以使用元组类型变量实现您想要的。您可以简单地提供错误消息解释的当前不存在的隐式转换。例如,您可以将以下内容添加到 Size
类型:
public static implicit operator (int x, int y)(Size size)
{
return (size.W, size.H);
}
那么赋值就会随心所欲地在任何地方工作,而不仅仅是在 switch
语句中。
您可以从每种类型的部分创建一个元组:
case Size size:
xy = (size.Length, size.Height);
break;
case Point point:
xy = (point.X, point. Y);
break;