我正在使用 .NET 4.8 并使用 Deconstructor 声明一条记录:
public record Product
{
public string Name { get; }
public int CategoryId { get; }
public Product(string name, int categoryId)
=> (Name, CategoryId) = (name, categoryId);
public void Deconstruct(out string name, out int categoryId)
=> (name, categoryId) = (Name, CategoryId);
}
Run Code Online (Sandbox Code Playgroud)
然后我使用以下已编译的代码,它工作正常:
var product = new Product("VideoGame", 1);
var (name, categoryId) = product;
string s = name;
int i = categoryId;
Run Code Online (Sandbox Code Playgroud)
虽然此代码不起作用,但会生成错误:
“错误 CS0029 无法将类型 'ConsoleApp4.Product' 隐式转换为 'System.Tuple<string, int>'”):
var product = new Product("VideoGame", 1);
Tuple<string, int> t = product;
string s = t.Item1;
int i = t.Item2;
Run Code Online (Sandbox Code Playgroud)
声明var (name, categoryId)不清楚。它是什么?
这个变量的类型是什么?规范中如何称呼这种结构?
这是在幕后自动生成的类型吗?name和categoryId是它的属性吗?
请注意语法
var (name, categoryId) = product;
Run Code Online (Sandbox Code Playgroud)
是一个解构- 它不是对元组的赋值。
从 C# 7.0 开始,您可以在单个解构操作中从元组中检索多个元素,或从对象中检索多个字段、属性和计算值。解构元组时,将其元素分配给各个变量。当您解构一个对象时,您可以将选定的值分配给各个变量。
Deconstruct暂时忽略一下,只要_提供足够的变量(或丢弃)来容纳元组,任何元组都可以解构为单独的变量。
例如
(string name, int categoryId) = ("Hello", 123);
Run Code Online (Sandbox Code Playgroud)
将“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);
Run Code Online (Sandbox Code Playgroud)
同样,通过为Deconstruct您自己的类/记录提供合适的重载或扩展方法,您可以将多个变量分配给out匹配Deconstruct方法的参数:
var (name, categoryId) = Product;
Run Code Online (Sandbox Code Playgroud)
它告诉编译器为 寻找适当的Deconstruct重载Product。在这种情况下,因为您对var所有解构函数使用类型推断,所以解构函数必须有 2 个参数(任何类型,将被推断)。
这里还发生了一些其他细微差别。
首先,正如您所看到的,您可以声明许多不同的解构以供Product记录,只要解构的签名不同即可。
(值)元组语法
public void Deconstruct(out string name, out int categoryId)
=> (name, categoryId) = (Name, CategoryId);
Run Code Online (Sandbox Code Playgroud)
只是一个方便的简写
public void Deconstruct(out string name, out int categoryId)
{
name = Name;
categoryId = CategoryId;
}
Run Code Online (Sandbox Code Playgroud)
当您进行以下分配时:
var (name, categoryId) = product;
Run Code Online (Sandbox Code Playgroud)
适当的解构重载位于Product,在本例中,因为您使用var类型推断,所以解构函数必须有 2 个参数(但可以是任何类型)。
然后将 out 变量分配给您的解构变量,您也将其命名为string name和int categoryId。
虽然您不能直接解构 INTO a System.ValueTupleor System.Tuple,但您可以从两者解构
var (name, categoryId) = Tuple.Create("Hello", 123); // Old Heap tuples
var (name, categoryId) = ("Hello", 123); // Newer value tuples
Run Code Online (Sandbox Code Playgroud)
解构的主要用途之一是在模式匹配期间用于简写符号,您可以在其中快速推理类型和属性:
例如代替
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"
};
Run Code Online (Sandbox Code Playgroud)
您可以根据需要解构和/或丢弃:
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"
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
324 次 |
| 最近记录: |