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

发布于 2024-08-04 21:27:50 字数 592 浏览 9 评论 0原文

我可以将数组中的每个值分配给 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# 中是否可行。

编辑:对于那些建议我将字符串“hey”和“now”分配给变量的人,这不是我想要的。想象一下以下情况:

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”的事实是任意的。事实上它可以返回任意两个值,它们甚至不必是字符串。

Can I assign each value in an array to separate variables in one line in C#? Here's an example in Ruby code of what I want:

irb(main):001:0> str1, str2 = ["hey", "now"]
=> ["hey", "now"]
irb(main):002:0> str1
=> "hey"
irb(main):003:0> str2
=> "now"

I'm not sure if what I'm wanting is possible in C#.

Edit: for those suggesting I just assign the strings "hey" and "now" to variables, that's not what I want. Imagine the following:

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

Now the fact that the method get_two_values returned strings "hey" and "now" is arbitrary. In fact it could return any two values, they don't even have to be strings.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

謌踐踏愛綪 2024-08-11 21:27:50

这在 C# 中是不可能的。

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

strArr = new string[]{"foo","bar"};
string str1 = strArr[0], str2 = strArr[1];

This is not possible in C#.

The closest thing I can think of is to use initialization in the same line with indexs

strArr = new string[]{"foo","bar"};
string str1 = strArr[0], str2 = strArr[1];
红玫瑰 2024-08-11 21:27:50

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

使用元组的另一种方法是解构它们。一个解构
声明是将元组(或其他值)拆分为的语法
它的各个部分并将这些部分单独分配给新变量:

(第一个字符串,中间的字符串,最后一个字符串) = LookupName(id1); // 解构声明
WriteLine($"找到{第一个} {最后一个}。");

在解构声明中,您可以使用 var 来表示个体
声明的变量:

(var first, var middle, var last) = LookupName(id1); // 里面的变量

或者甚至将单个 var 放在括号之外作为
缩写:

var (第一个、中间、最后一个) = LookupName(id1); // 外部变量

您还可以使用解构函数解构为现有变量
作业:

(第一个、中间、最后一个) = LookupName(id2); // 解构赋值

解构不仅仅适用于元组。任何类型都可以被解构,
只要它有一个(实例或扩展)解构方法
形式:

public void Deconstruct(out T1 x1, ..., out Tn xn) { ... }

输出参数构成由
解构。

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

类点
{
    公共 int X { 得到; }
    公共 int Y { 得到; }

    公共点(int x,int y){X = x; Y = y; }
    公共无效解构(out int x,out int y){x = X; y = Y; }
}

(var myX, var myY) = GetPoint(); // 调用 Deconstruct(out myX, out myY);

构造函数和解构函数将成为一种常见模式
这样就“对称”了。
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;
    });
}

这样:

  • 您可以避免像 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

Update: In C#7 you can easily assign multiple variables at once using tuples. In order to assign array elements to variables, you'd need to write an appropriate Deconstruct() extension methods:

Another way to consume tuples is to deconstruct them. A deconstructing
declaration is a syntax for splitting a tuple (or other value) into
its parts and assigning those parts individually to fresh variables:

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

In a deconstructing declaration you can use var for the individual
variables declared:

(var first, var middle, var last) = LookupName(id1); // var inside

Or even put a single var outside of the parentheses as an
abbreviation:

var (first, middle, last) = LookupName(id1); // var outside

You can also deconstruct into existing variables with a deconstructing
assignment:

(first, middle, last) = LookupName(id2); // deconstructing assignment

Deconstruction is not just for tuples. Any type can be deconstructed,
as long as it has an (instance or extension) deconstructor method of
the form:

public void Deconstruct(out T1 x1, ..., out Tn xn) { ... }

The out parameters constitute the values that result from the
deconstruction.

(Why does it use out parameters instead of returning a tuple? That is
so that you can have multiple overloads for different numbers of
values).

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);

It will be a common pattern to have constructors and deconstructors be
“symmetric” in this way.
https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/


Old answer:

In fact, you can achieve similar functionality in C# by using extension methods like this (note: I haven't include checking if arguments are valid):

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]);
}
//...

And you can use them like this:

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

In case a return value from a function is needed, the following overload would work:

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;
    });
}

In this way:

  • You avoid having to repeat array name like in solution proposed by JaredPar and others; the list of "variables" is easy to read.

  • You avoid having to explicitly declare variables types like in Daniel Earwicker's solution.

The disadvantage is that you end up with additional code block, but I think it's worth it. You can use code snippets in order to avoid typing braces etc. manually.

I know it's a 7 years old question, but not so long time ago I needed such a solution - easy giving names to array elements passed into the method (no, using classes/structs instead of arrays wasn't practical, because for same arrays I could need different element names in different methods) and unfortunately I ended up with code like this:

var A = points[0];
var A2 = points[1];
var B = points[2];
var C2 = points[3];
var C = points[4];

Now I could write (in fact, I've refactored one of those methods right now!):

points.Match((A, A2, B, C2, C) => {...});

My solution is similar to pattern matching in F# and I was inspired by this answer: https://stackoverflow.com/a/2321922/6659843

望喜 2024-08-11 21:27:50

现实世界的用例是提供一种从函数返回多个值的便捷方法。因此,它是一个在数组中返回固定数量值的 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。这将是对语言的非破坏性更改,因为 var 当前的合法使用非常严格,因此上述“多重声明”语法还没有有效的使用。

The real-world use case for this is providing a convenient way to return multiple values from a function. So it is a Ruby function that returns a fixed number of values in the array, and the caller wants them in two separate variables. This is where the feature makes most sense:

first_name, last_name = get_info() // always returns an array of length 2

To express this in C# you would mark the two parameters with out in the method definition, and return void:

public static void GetInfo(out string firstName, out string lastName)
{
    // assign to firstName and lastName, instead of trying to return them.
}

And so to call it:

string firstName, lastName;
SomeClass.GetInfo(out firstName, out lastName);

It's not so nice. Hopefully some future version of C# will allow this:

var firstName, lastName = SomeClass.GetInfo();

To enable this, the GetInfo method would return a Tuple<string, string>. This would be a non-breaking change to the language as the current legal uses of var are very restrictive so there is no valid use yet for the above "multiple declaration" syntax.

温馨耳语 2024-08-11 21:27:50

您可以在一行中完成它,但不能作为一个语句来完成。

例如:

int str1 = "hey"; int str2 = "now";

Python 和 ruby​​ 支持您尝试执行的作业; C# 没有。

You can do it in one line, but not as one statement.

For example:

int str1 = "hey"; int str2 = "now";

Python and ruby support the assignment you're trying to do; C# does not.

鸠书 2024-08-11 21:27:50

您可以将命名元组与 C# 7

{
  (string part1, string part2) = Deconstruct(new string[]{"hey","now"});
}

public (string, string) Deconstruct(string[] parts)
{
   return (parts[0], parts[1]);
}

You can use named tuples with C# 7 now.

{
  (string part1, string part2) = Deconstruct(new string[]{"hey","now"});
}

public (string, string) Deconstruct(string[] parts)
{
   return (parts[0], parts[1]);
}
音栖息无 2024-08-11 21:27:50

我不确定我想要的是不是
在 C# 中可以实现。

它不是。

I'm not sure if what I'm wanting is
possible in C#.

It's not.

白云悠悠 2024-08-11 21:27:50

不,但是您可以初始化一个字符串数组:

string[] strings = new string[] {"hey", "now"};

尽管这对您来说可能不太有用。坦率地说,将它们分成两行并不难:

string str1 = "hey";
string str2 = "now";

No, but you can initialize an array of strings:

string[] strings = new string[] {"hey", "now"};

Although that's probably not too useful for you. Frankly its not hard to put them on two lines:

string str1 = "hey";
string str2 = "now";
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文