Assign values of array to separate variables in one line

前端 未结 8 1500
感情败类
感情败类 2020-12-11 00:24

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          


        
相关标签:
8条回答
  • 2020-12-11 00:42

    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.

    0 讨论(0)
  • 2020-12-11 00:43

    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";
    
    0 讨论(0)
  • 2020-12-11 00:48

    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];
    
    0 讨论(0)
  • 2020-12-11 00:53

    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

    0 讨论(0)
  • 2020-12-11 00:56

    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.

    0 讨论(0)
  • 2020-12-11 00:56

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

    It's not.

    0 讨论(0)
提交回复
热议问题