请注意语法
var (name, categoryId) = product;
这是一种析构,而不是分配给元组的操作。
来自官方文档
从 C# 7.0 开始,您可以在单个析构操作中检索元组的多个元素或检索对象中的多个字段、属性和计算值。当你析构一个元组时,你将其元素分配给单独的变量。当你析构一个对象时,你将选定的值分配给单独的变量。
暂且不考虑 Deconstruct
,任何元组都可以被析构成单独的变量,只要提供足够的变量(或抛弃使用的变量,_
)来容纳该元组即可。
例如:
(string name, int categoryId) = ("Hello", 123);
将"Hello"分配给name
,并将123分配给categoryId
以下所有内容都是等效的
(string name, int categoryId) = ("Hello", 123); // Types of tuple match position vars
(var name, var categoryId) = ("Hello", 123); // Type variable types are inferred
var (name, categoryId) = ("Hello", 123);
同样地,通过为您自己的类/记录提供适当的Deconstruct
重载或扩展方法,您可以将多个变量分配给匹配的Deconstruct
方法的out
参数:
var (name, categoryId) = Product;
这告诉编译器为Product
查找一个合适的Deconstruct
重载。因为你对所有已析构的变量使用了var
类型推断,所以析构函数必须有两个参数(任意类型,将被推断)。
这里还有一些其他微妙之处。
首先,如你所见,你可以为Product
记录声明许多不同的析构函数,只要这些析构函数的签名不同即可。
值元组语法
public void Deconstruct(out string name, out int categoryId)
=> (name, categoryId) = (Name, CategoryId);
仅仅是一个方便的简写
public void Deconstruct(out string name, out int categoryId)
{
name = Name;
categoryId = CategoryId;
}
当您执行以下赋值操作时:
var (name, categoryId) = product;
在这种情况下,由于您使用了var
类型推断,因此为Product
找到了适当的解构重载,该解构必须具有2个参数(但可以是任何类型)。
然后,将out变量分配给您的解构变量,您也将它们命名为string name
和int categoryId
。
尽管您无法直接将其解构为System.ValueTuple
或System.Tuple
,但您可以从两者中进行解构。
var (name, categoryId) = Tuple.Create("Hello", 123); // Old Heap tuples
var (name, categoryId) = ("Hello", 123); // Newer value tuples
Deconstruction的主要用途之一是在
模式匹配期间进行简写符号,您可以快速推理类型和属性:
例如,而不是
var result = product switch
{
Product x when x.CategoryId == 3 => "You've got a category 3 product",
Product x when string.IsNullOrWhiteSpace(x.Name) => "That product looks broken",
_ => "Just a standard product"
};
你可以将其拆解和/或丢弃,以满足需要。
var result2 = product switch
{
var (_, cat) when cat == 3 => "You've got a category 3 product",
var (str, _) when string.IsNullOrWhiteSpace(str) => "That product looks broken",
_ => "Just a standard product"
};
record
中,你无需编写Deconstruct
方法,因为它会被自动生成,除非你需要自定义它。你的record
可以重写为public record Product(string Name, int CategoryId);
,并且它将意味着完全相同的事情。 - Aluan Haddadvar
可以自动推断类型。它并不指向任何特定的类型。 - Beingninvar (name, categoryId) = product;
,那么您也可以写成(string name, int categoryId) = product;
。这样您就可以直接看到变量的类型了。 - SomeBody记录
类型是C# 9.0的新功能,而且c# 9.0仅支持.NET 5。我错过了什么吗?您是如何使用.NET 4.8编译此内容的? - Igor