将数组的值分配给一行中的变量

Sar*_*els 21 c# arrays string initialization declaration

我可以将数组中的每个值分配给C#中的一行中的变量吗?这是Ruby代码中我想要的一个例子:

irb(main):001:0> str1, str2 = ["hey", "now"]
=> ["hey", "now"]
irb(main):002:0> str1
=> "hey"
irb(main):003:0> str2
=> "now"
Run Code Online (Sandbox Code Playgroud)

我不确定我在C#中是否可能需要什么.

编辑: 对于那些暗示我只是将字符串"嘿"和"现在"分配给变量的人,这不是我想要的.想象一下:

irb(main):004:0> val1, val2 = get_two_values()
=> ["hey", "now"]
irb(main):005:0> val1
=> "hey"
irb(main):006:0> val2
=> "now"
Run Code Online (Sandbox Code Playgroud)

现在,该方法get_two_values返回字符串"hey"和"now" 的事实是任意的.实际上它可以返回任何两个值,它们甚至不必是字符串.

Jar*_*Par 14

这在C#中是不可能的.

我能想到的最接近的事情是在索引相同的行中使用初始化

strArr = new string[]{"foo","bar"};
string str1 = strArr[0], str2 = strArr[1];
Run Code Online (Sandbox Code Playgroud)


use*_*562 11

更新:在C#7中,您可以使用元组轻松地一次分配多个变量.为了将数组元素分配给变量,您需要编写适当的Deconstruct()扩展方法:

消耗元组的另一种方法是解构它们.解构声明是将元组(或其他值)拆分为其部分并将这些部分分别分配给新变量的语法:

(string first, string middle, string last) = LookupName(id1); // deconstructing declaration
WriteLine($"found {first} {last}.");
Run Code Online (Sandbox Code Playgroud)

在解构声明中,您可以对声明的各个变量使用var:

(var first, var middle, var last) = LookupName(id1); // var inside
Run Code Online (Sandbox Code Playgroud)

或者甚至在括号外面放一个var作为缩写:

var (first, middle, last) = LookupName(id1); // var outside
Run Code Online (Sandbox Code Playgroud)

您还可以使用解构赋值来解构现有变量:

(first, middle, last) = LookupName(id2); // deconstructing assignment
Run Code Online (Sandbox Code Playgroud)

解构不只是为了元组.任何类型都可以解构,只要它具有形式的(实例或扩展)解构函数方法:

public void Deconstruct(out T1 x1, ..., out Tn xn) { ... }
Run Code Online (Sandbox Code Playgroud)

out参数构成解构所产生的值.

(为什么它使用out参数而不是返回元组?这样就可以为不同数量的值设置多个重载).

class Point
{
    public int X { get; }
    public int Y { get; }

    public Point(int x, int y) { X = x; Y = y; }
    public void Deconstruct(out int x, out int y) { x = X; y = Y; }
}

(var myX, var myY) = GetPoint(); // calls Deconstruct(out myX, out myY);
Run Code Online (Sandbox Code Playgroud)

以这种方式使构造函数和解构函数"对称"将是一种常见的模式. https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/


老答案:

实际上,你可以通过使用这样的扩展方法在C#中实现类似的功能(注意:我没有包括检查参数是否有效):

public static void Match<T>(this IList<T> collection, Action<T,T> block)
{
    block(collection[0], collection[1]);
}
public static void Match<T>(this IList<T> collection, Action<T,T,T> block)
{
    block(collection[0], collection[1], collection[2]);
}
//...
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它们:

new[] { "hey", "now" }.Match((str1, str2) =>
{
    Console.WriteLine(str1);
    Console.WriteLine(str2);
});
Run Code Online (Sandbox Code Playgroud)

如果需要函数的返回值,则以下重载将起作用:

public static R Match<T,R>(this IList<T> collection, Func<T, T, R> block)
{
    return block(collection[0], collection[1]);
}

private string NewMethod1()
{   
    return new[] { "hey", "now" }.Match((str1, str2) =>
    {
        return str1 + str2;
    });
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式:

  • 您可以避免像JaredPar和其他人提出的解决方案那样重复数组名称; "变量"列表很容易阅读.

  • 您可以避免在Daniel Earwicker的解决方案中明确声明变量类型.

缺点是你最终得到了额外的代码块,但我认为这是值得的.您可以使用代码段以避免手动键入大括号等.

我知道这是一个7年前的问题,但不久以前我需要这样一个解决方案 - 容易给出传递给方法的数组元素的名称(不,使用类/结构而不是数组是不切实际的,因为对于相同的数组我可能需要在不同的方法中使用不同的元素名称),不幸的是我最终得到了这样的代码:

var A = points[0];
var A2 = points[1];
var B = points[2];
var C2 = points[3];
var C = points[4];
Run Code Online (Sandbox Code Playgroud)

现在我可以写(事实上,我现在已经重构了其中一种方法!):

points.Match((A, A2, B, C2, C) => {...});
Run Code Online (Sandbox Code Playgroud)

我的解决方案类似于F#中的模式匹配,我的灵感来自于这个答案:https://stackoverflow.com/a/2321922/6659843