首页 > 解决方案 > 组中变量的 C# 赋值

问题描述

哪些 C# 功能(如果有)允许您编写如下代码: (a, b, c) = (3, 4, 5);

标签: c#.net

解决方案


这是 C# 7 中引入的新元组语法。

您需要先声明变量,除非该语句var前面写有 with,因此其中任何一个都可以:

var (a, b, c) = (3, 4, 5);

或者:

int a, b, c;
(a, b, c) = (3, 4, 5);

这两个都相当于:

int a = 3;
int b = 4;
int c = 5;

请注意,这不会构造tuple,它使用 C# 7 获得的新 tuple语法,因此编译后的 IL 实际上与上面的最后一段代码相同(向下滚动以证明这一点。)

元组已添加到 .NET Framework 4.7.1 和 .NET Core 2.1(我认为),或者如果您使用的是较旧的 .NET Framework/Core/Standard 版本,则可以通过 nuget 包添加。

然而,新语法和元组的概念也被添加到 C# 中,既作为构造这些元组类型实例的花哨语法,又作为 C# 语言中的核心概念

例如,要交换两个变量(相同类型)的内容,您现在可以使用以下语法:

(x, y) = (y, x);

这不会构造一个新的元组实例,并且在功能上与此相同:

var temp = x;
x = y;
y = x;

尽管在这里编译器可以从访问难以编写 C# 代码的 IL 指令中受益。上面的交换(使用元组语法)被编译成这样:

ldarg.2
ldarg.1
starg.s 02 // store v1 into v2
starg.s 01 // store v2 into v1

为了证明我前面提到的两段代码确实是相同的,我在LINQPad中执行了以下代码,然后检查了 LINQPad 可以显示的 IL,我将这两种方法并排放置,以便您可以看到相似之处:

public void Test1()
{
    int a, b, c;
    (a, b, c) = (3, 4, 5);

    a.Dump();
    b.Dump();
    c.Dump();
}

public void Test2()
{
    int a = 3;
    int b = 4;
    int c = 5;

    a.Dump();
    b.Dump();
    c.Dump();
}

IL 输出:

Test1:                                                           Test2:
IL_0000:  ldc.i4.3                                               IL_0000:  ldc.i4.3    
IL_0001:  ldc.i4.4                                               IL_0001:  ldc.i4.4    
IL_0002:  stloc.0     // b                                       IL_0002:  stloc.0     // b
IL_0003:  ldc.i4.5                                               IL_0003:  ldc.i4.5    
IL_0004:  stloc.1     // c                                       IL_0004:  stloc.1     // c
IL_0005:  call        LINQPad.Extensions.Dump<Int32>             IL_0005:  call        LINQPad.Extensions.Dump<Int32>
IL_000A:  pop                                                    IL_000A:  pop         
IL_000B:  ldloc.0     // b                                       IL_000B:  ldloc.0     // b
IL_000C:  call        LINQPad.Extensions.Dump<Int32>             IL_000C:  call        LINQPad.Extensions.Dump<Int32>
IL_0011:  pop                                                    IL_0011:  pop         
IL_0012:  ldloc.1     // c                                       IL_0012:  ldloc.1     // c
IL_0013:  call        LINQPad.Extensions.Dump<Int32>             IL_0013:  call        LINQPad.Extensions.Dump<Int32>
IL_0018:  pop                                                    IL_0018:  pop         
IL_0019:  ret                                                    IL_0019:  ret         

推荐阅读