Интерфейс является контрактом, которого придерживаются все классы с реализацией. Это означает, что они должны придерживаться всего этого или ни одного из него.
, Если бы интерфейс общедоступен тогда, каждая часть того контакта должна быть общедоступной, иначе это значило бы тот для друга классы / внутренние классы и другая вещь для всего остального.
Или используйте абстрактный базовый класс или (если возможный и практичный) метод внутреннего добавочного номера в интерфейсе .
Чтобы избежать создания дополнительного массива, вы можете сделать следующее:
var builder = new StringBuilder();
Array.ForEach(arr, x => builder.Append(x));
var res = builder.ToString();
at.net 3.5 use:
String.Join("", new List<int>(array).ConvertAll(i => i.ToString()).ToArray());
at.net 4.0 или выше используйте: (см. Ответ @Jan Remunda)
string result = string.Join("", array);
string result = arr.Aggregate("", (s, i) => s + i.ToString());
(Отказ от ответственности: если у вас много цифр (сотни, по крайней мере), и вам не все равно Что касается производительности, я предлагаю отказаться от этого метода и использовать StringBuilder
, как в ответе JaredPar.)
You can do:
int[] arr = {0,1,2,3,0,1};
string results = string.Join("",arr.Select(i => i.ToString()).ToArray());
That gives you your results.
I like using StringBuilder
with Aggregate()
. The "trick" is that Append()
returns the StringBuilder
instance itself:
var sb = arr.Aggregate( new StringBuilder(), ( s, i ) => s.Append( i ) );
var result = sb.ToString();
string.Join("", (from i in arr select i.ToString()).ToArray())
В .NET 4.0 строка .Join
может использовать IEnumerable
напрямую:
string.Join("", from i in arr select i.ToString())
I've left this here for posterity but don't recommend its use as it's not terribly readable. This is especially true now that I've come back to see if after a period of some time and have wondered what I was thinking when I wrote it (I was probably thinking 'crap, must get this written before someone else posts an answer'.)
string s = string.Concat(arr.Cast<object>().ToArray());
Я понимаю, что мое мнение, вероятно, не является популярным, но я думаю, мне трудно запрыгнуть на универсал Linq-y. Это здорово. Это сжато. Я понимаю это и не возражаю против использования там, где это уместно. Может быть, это только я, но я чувствую, что люди перестали думать о создании служебных функций для выполнения того, что они хотят, и вместо этого предпочитают засорять свой код (иногда) чрезмерно длинными строками кода Linq ради создания плотного однострочного кода.
Я не говорю, что какой-либо из ответов Linq, которые здесь предоставили, плохие, но я полагаю, что есть вероятность того, что эти отдельные строки кода могут начать становиться длиннее и более неясными по мере необходимости справляться с различными ситуациями. Что делать, если ваш массив равен нулю? Что, если вам нужна строка с разделителями, а не просто конкатенация? Что, если некоторые из целых чисел в вашем массиве являются двузначными, и вы хотите дополнить каждое значение ведущими нулями, чтобы строка для каждого элемента имела ту же длину, что и остальные?
В качестве примера возьмем один из предоставленных ответов. :
result = arr.Aggregate(string.Empty, (s, i) => s + i.ToString());
Если мне нужно беспокоиться о том, что массив является нулевым, теперь он становится таким:
result = (arr == null) ? null : arr.Aggregate(string.Empty, (s, i) => s + i.ToString());
Если мне нужна строка с разделителями-запятыми, теперь она становится такой:
result = (arr == null) ? null : arr.Skip(1).Aggregate(arr[0].ToString(), (s, i) => s + "," + i.ToString());
Это все еще неплохо, но я думаю с первого взгляда не очевидно, что делает эта строка кода.
Конечно, ничто не мешает вам добавить эту строку кода в вашу собственную служебную функцию, чтобы у вас не было этого долгого беспорядка, смешанного с вашим приложением логика, особенно если вы делаете это в нескольких местах:
public static string ToStringLinqy<T>(this T[] array, string delimiter)
{
// edit: let's replace this with a "better" version using a StringBuilder
//return (array == null) ? null : (array.Length == 0) ? string.Empty : array.Skip(1).Aggregate(array[0].ToString(), (s, i) => s + "," + i.ToString());
return (array == null) ? null : (array.Length == 0) ? string.Empty : array.Skip(1).Aggregate(new StringBuilder(array[0].ToString()), (s, i) => s.Append(delimiter).Append(i), s => s.ToString());
}
Но если вы ' вы все равно собираетесь поместить его в служебную функцию, действительно ли вам нужно, чтобы он был сжат до однострочника? В таком случае почему бы не добавить несколько дополнительных строк для ясности и не воспользоваться StringBuilder, чтобы не выполнять повторяющиеся операции конкатенации:
public static string ToStringNonLinqy<T>(this T[] array, string delimiter)
{
if (array != null)
{
// edit: replaced my previous implementation to use StringBuilder
if (array.Length > 0)
{
StringBuilder builder = new StringBuilder();
builder.Append(array[0]);
for (int i = 1; i < array.Length; i++)
{
builder.Append(delimiter);
builder.Append(array[i]);
}
return builder.ToString()
}
else
{
return string.Empty;
}
}
else
{
return null;
}
}
И если вас действительно так беспокоит производительность, вы можете даже превратить его в гибридная функция, которая решает, делать ли string.Join или использовать StringBuilder в зависимости от того, сколько элементов находится в массиве (это микрооптимизация, которую, на мой взгляд, не стоит делать и, возможно, более вредно, чем полезно, но я используя его в качестве примера для этой проблемы):
public static string ToString<T>(this T[] array, string delimiter)
{
if (array != null)
{
// determine if the length of the array is greater than the performance threshold for using a stringbuilder
// 10 is just an arbitrary threshold value I've chosen
if (array.Length < 10)
{
// assumption is that for arrays of less than 10 elements
// this code would be more efficient than a StringBuilder.
// Note: this is a crazy/pointless micro-optimization. Don't do this.
string[] values = new string[array.Length];
for (int i = 0; i < values.Length; i++)
values[i] = array[i].ToString();
return string.Join(delimiter, values);
}
else
{
// for arrays of length 10 or longer, use a StringBuilder
StringBuilder sb = new StringBuilder();
sb.Append(array[0]);
for (int i = 1; i < array.Length; i++)
{
sb.Append(delimiter);
sb.Append(array[i]);
}
return sb.ToString();
}
}
else
{
return null;
}
}
В этом примере влияние на производительность, вероятно, не заслуживает внимания, но дело в том, что если вы находитесь в ситуации, когда вам действительно нужно заботиться о производительности ваших операций, какими бы они ни были, то, скорее всего, будет проще и удобнее обрабатывать это в служебной функции, чем использовать сложное выражение Linq.
Эта служебная функция все еще выглядит неуклюже. Теперь давайте откажемся от гибридных вещей и сделаем следующее:
// convert an enumeration of one type into an enumeration of another type
public static IEnumerable<TOut> Convert<TIn, TOut>(this IEnumerable<TIn> input, Func<TIn, TOut> conversion)
{
foreach (TIn value in input)
{
yield return conversion(value);
}
}
// concatenate the strings in an enumeration separated by the specified delimiter
public static string Delimit<T>(this IEnumerable<T> input, string delimiter)
{
IEnumerator<T> enumerator = input.GetEnumerator();
if (enumerator.MoveNext())
{
StringBuilder builder = new StringBuilder();
// start off with the first element
builder.Append(enumerator.Current);
// append the remaining elements separated by the delimiter
while (enumerator.MoveNext())
{
builder.Append(delimiter);
builder.Append(enumerator.Current);
}
return builder.ToString();
}
else
{
return string.Empty;
}
}
// concatenate all elements
public static string ToString<T>(this IEnumerable<T> input)
{
return ToString(input, string.Empty);
}
// concatenate all elements separated by a delimiter
public static string ToString<T>(this IEnumerable<T> input, string delimiter)
{
return input.Delimit(delimiter);
}
// concatenate all elements, each one left-padded to a minimum length
public static string ToString<T>(this IEnumerable<T> input, int minLength, char paddingChar)
{
return input.Convert(i => i.ToString().PadLeft(minLength, paddingChar)).Delimit(string.Empty);
}
Теперь у нас есть отдельные и довольно компактные служебные функции, каждая из которых, возможно, полезна сама по себе.
В конечном счете, я не говорю, что вы не должны использовать Linq, Скорее всего, не забывайте о преимуществах создания собственных служебных функций, даже если они небольшие и, возможно, содержат только одну строку, которая возвращает результат из строки кода Linq. По крайней мере, вы я смогу сохранить код вашего приложения еще более сжатым, чем вы могли бы достичь с помощью строки кода Linq, и если вы используете его в нескольких местах, то использование служебной функции упрощает настройку вывода, если вам нужно изменить это позже.
Для этой проблемы я бы предпочел просто написать что-то вроде этого в моем коде приложения:
int[] arr = { 0, 1, 2, 3, 0, 1 };
// 012301
result = arr.ToString<int>();
// comma-separated values
// 0,1,2,3,0,1
result = arr.ToString(",");
// left-padded to 2 digits
// 000102030001
result = arr.ToString(2, '0');
The most efficient way is not to convert each int into a string, but rather create one string out of an array of chars. Then the garbage collector only has one new temp object to worry about.
int[] arr = {0,1,2,3,0,1};
string result = new string(Array.ConvertAll<int,char>(arr, x => Convert.ToChar(x + '0')));