Присваивать значения массива отдельным переменным в одной строке

StackOverflow https://stackoverflow.com/questions/1422155

Вопрос

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

Это было полезно?

Решение

Это невозможно в 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 (first, middle, last) = LookupName(id1); // var outside

Вы также можете выполнить деконструкцию в существующие переменные с помощью деконструирующего присваивания:

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

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

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

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

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

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

Например:

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

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

  

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

Это не так.

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

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

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

        int x, y;
        int[] arr = new int[] { x = 1, y = 2 };

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

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]);
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top