我可以在一个阵列中的一行在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
返回的字符串“嗨”和“现在”是任意的。 事实上,它可以返回任何两个值,他们甚至不必是字符串。
这是不可能在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
解构不只是元组。 任何类型的可被解构,只要它有一个(实例或扩展)的形式的解构方法:
public void Deconstruct(out T1 x1, ..., out Tn xn) { ... }
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);
这将是一个常见的模式有构造函数和deconstructors在这样的“对称”。 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]);
}
//...
你也可以使用它们像这样:
new[] { "hey", "now" }.Match((str1, str2) =>
{
Console.WriteLine(str1);
Console.WriteLine(str2);
});
在情况下,需要从一个函数返回值,下面的过载会的工作:
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;
});
}
通过这种方式:
缺点是,你最终有额外的代码块,但我认为这是值得的。 您可以使用代码片段,以避免手动输入括号等。
我知道这是一个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功能,调用者希望他们在两个独立的变量。 这是功能最有意义:
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();
为了实现这一点,所述GetInfo
方法将返回一个Tuple<string, string>
。 这将是一个非重大更改的语言作为当前合法用途var
非常严格,所以没有有效使用且对于上述的“多重声明”语法。
您可以在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]);
}