Присвойте значения массива отдельным переменным в одной строке - PullRequest
21 голосов
/ 14 сентября 2009

Можно ли назначить каждое значение в массиве отдельным переменным в одной строке в 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", является произвольным. Фактически он может возвращать любые два значения, они даже не должны быть строками.

Ответы [ 8 ]

14 голосов
/ 14 сентября 2009

Это невозможно в C #.

Самое близкое, что я могу придумать, это использовать инициализацию в одной строке с индексами

strArr = new string[]{"foo","bar"};
string str1 = strArr[0], str2 = strArr[1];
11 голосов
/ 16 августа 2016

Обновление: В 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 (first, middle, last) = LookupName(id1); // var outside

Вы также можете деконструировать в существующие переменные с деконструкцией Назначение:

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

Деконструкция не только для кортежей. Любой тип может быть деконструирован, до тех пор, пока он имеет (экземпляр или расширение) метод деконструктора форма:

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

Выходные параметры представляют собой значения, которые являются результатом деконструкция.

(Почему он использует параметры вместо возврата кортежа? так что вы можете иметь несколько перегрузок для разных номеров значения).

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 #, используя такие методы расширения (примечание: я не включил проверку правильности аргументов):

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 и другими; список «переменных» легко читается.

  • Вам не нужно явно объявлять типы переменных, как в решении Даниэля Эрвикера.

Недостаток в том, что вы получаете дополнительный блок кода, но я думаю, что оно того стоит. Вы можете использовать фрагменты кода, чтобы не вводить фигурные скобки и т.д. вручную.

Я знаю, что это вопрос 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

4 голосов
/ 28 марта 2010

Реальный вариант использования для этого предоставляет удобный способ возврата нескольких значений из функции. Так что это функция 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 очень ограничительно, поэтому пока нет действительного использования вышеупомянутого синтаксиса «множественного объявления».

2 голосов
/ 24 июля 2010

Вы можете сделать это в C #

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

или вы можете быть таким же

        int x, y;
        int[] arr = new int[] { x = 1, y = 2 };
2 голосов
/ 14 сентября 2009

Я не уверен, что то, что я хочу, это возможно в C #.

Это не так.

2 голосов
/ 14 сентября 2009

Вы можете сделать это в одной строке, но не как одно утверждение.

Например:

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

Python и ruby ​​поддерживают назначение, которое вы пытаетесь выполнить; C # нет.

0 голосов
/ 19 декабря 2017

Теперь вы можете использовать именованные кортежи с C # 7 .

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

public (string, string) Deconstruct(string[] parts)
{
   return (parts[0], parts[1]);
}
0 голосов
/ 14 сентября 2009

Нет, но вы можете инициализировать массив строк:

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

Хотя это, вероятно, не слишком полезно для вас. Честно говоря, их нетрудно поместить в две строки:

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