将数组的值分配给一行中的变量
我可以将数组中的每个值分配给C#中的一行中的变量吗? 这是Ruby代码中我想要的一个例子:
irb(main):001:0> str1, str2 = ["hey", "now"] => ["hey", "now"] irb(main):002:0> str1 => "hey" irb(main):003:0> str2 => "now"
我不确定我在C#中是否可能需要什么。
编辑:对于那些暗示我只是将字符串“嘿”和“现在”分配给变量的人,这不是我想要的。 想象一下:
irb(main):004:0> val1, val2 = get_two_values() => ["hey", "now"] irb(main):005:0> val1 => "hey" irb(main):006:0> val2 => "now"
现在get_two_values
方法返回字符串“hey”和“now”的事实是任意的。 实际上它可以返回任何两个值,它们甚至不必是字符串。
这在C#中是不可能的。
我能想到的最接近的事情是在索引相同的行中使用初始化
strArr = new string[]{"foo","bar"}; string str1 = strArr[0], str2 = strArr[1];
更新:在C#7中,您可以使用元组轻松地一次分配多个变量。 为了将数组元素分配给变量,您需要编写适当的Deconstruct()
扩展方法:
消耗元组的另一种方法是解构它们。 解构声明是将元组(或其他值)拆分为其部分并将这些部分分别分配给新变量的语法:
(string first, string middle, string last) = LookupName(id1); // deconstructing declaration WriteLine($"found {first} {last}.");
在解构声明中,您可以对声明的各个变量使用var:
(var first, var middle, var last) = LookupName(id1); // var inside
或者甚至在括号外面放一个var作为缩写:
var (first, middle, last) = LookupName(id1); // var outside
您还可以使用解构赋值来解构现有变量:
(first, middle, last) = LookupName(id2); // deconstructing assignment
解构不只是为了元组。 任何类型都可以解构,只要它具有forms的(实例或扩展)解构方法:
public void Deconstruct(out T1 x1, ..., out Tn xn) { ... }
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);
以这种方式使构造函数和解构函数“对称”将是一种常见的模式。 https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/
老答案:
事实上,你可以通过使用这样的扩展方法在C#中实现类似的function(注意:我没有包括检查参数是否有效):
public static void Match(this IList collection, Action block) { block(collection[0], collection[1]); } public static void Match (this IList collection, Action block) { block(collection[0], collection[1], collection[2]); } //...
你可以像这样使用它们:
new[] { "hey", "now" }.Match((str1, str2) => { Console.WriteLine(str1); Console.WriteLine(str2); });
如果需要函数的返回值,则以下重载将起作用:
public static R Match(this IList collection, Func block) { return block(collection[0], collection[1]); } private string NewMethod1() { return new[] { "hey", "now" }.Match((str1, str2) => { return str1 + str2; }); }
通过这种方式:
-
您可以避免像JaredPar和其他人提出的解决方案那样重复数组名称; “变量”列表很容易阅读。
-
您可以避免在Daniel Earwicker的解决方案中明确声明变量类型。
缺点是你最终得到了额外的代码块,但我认为这是值得的。 您可以使用代码段以避免手动键入大括号等。
我知道这是一个7年前的问题,但不久前我需要这样一个解决方案 – 轻松给出传递给方法的数组元素的名称(不,使用类/结构代替数组是不切实际的,因为对于相同的数组我可能需要在不同的方法中使用不同的元素名称),不幸的是我最终得到了这样的代码:
var A = points[0]; var A2 = points[1]; var B = points[2]; var C2 = points[3]; var C = points[4];
现在我可以写(事实上,我现在已经重构了其中一种方法!):
points.Match((A, A2, B, C2, C) => {...});
我的解决方案类似于F#中的模式匹配,我的灵感来自于这个答案: https : //stackoverflow.com/a/2321922/6659843
实际的用例是提供一种从函数返回多个值的便捷方法。 所以它是一个Ruby函数,它在数组中返回固定数量的值,调用者希望它们在两个单独的变量中。 这是该function最有意义的地方:
first_name, last_name = get_info() // always returns an array of length 2
要在C#中表达这一点,您将在方法定义中使用out
标记两个参数,并返回void
:
public static void GetInfo(out string firstName, out string lastName) { // assign to firstName and lastName, instead of trying to return them. }
所以称之为:
string firstName, lastName; SomeClass.GetInfo(out firstName, out lastName);
这不太好。 希望C#的未来版本允许这样:
var firstName, lastName = SomeClass.GetInfo();
要启用此function, GetInfo
方法将返回Tuple
。 这将是对语言的非破坏性更改,因为var
的当前合法使用非常严格,因此对于上述“多重声明”语法尚未有效使用。
我不确定我在C#中是否可能需要什么。
不是。
你可以在C#中做到这一点
string str1 = "hey", str2 = "now";
或者你可以这样想
int x, y; int[] arr = new int[] { x = 1, y = 2 };
您可以在一行中完成,但不能作为一个语句。
例如:
int str1 = "hey"; int str2 = "now";
Python和ruby支持你正在尝试的任务; C#没有。
不,但您可以初始化一个字符串数组:
string[] strings = new string[] {"hey", "now"};
虽然这对你来说可能不太有用。 坦率地说,不难将它们分为两行:
string str1 = "hey"; string str2 = "now";
您现在可以使用C#7命名元组。
{ (string part1, string part2) = Deconstruct(new string[]{"hey","now"}); } public (string, string) Deconstruct(string[] parts) { return (parts[0], parts[1]); }