Присваивать значения массива отдельным переменным в одной строке
-
07-07-2019 - |
Вопрос
Могу ли я присвоить каждое значение в массиве отдельным переменным в одной строке в 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]);
}