Я часто пишу такой код:
List<int> list = new List<int> { 1, 3, 5 };
foreach (int i in list) {
Console.Write("{0}\t", i.ToString()); }
Console.WriteLine();
Лучше было бы примерно так:
List<int> list = new List<int> { 1, 3, 5 };
Console.WriteLine("{0}\t", list);
Я подозреваю, что есть какой-нибудь хитрый способ сделать это, но я этого не вижу. Есть ли у кого-нибудь лучшее решение, чем первый блок?





Сделай это:
list.ForEach(i => Console.Write("{0}\t", i));
Обновлено: для других, кто ответил - он хочет, чтобы все они были в одной строке с вкладками между ними. :)
List<int> a = new List<int>() { 1, 2, 3, 4, 5 };
a.ForEach(p => Console.WriteLine(p));
редактировать: аааа он меня опередил.
list.ForEach(x=>Console.WriteLine(x));
List<int> list = new List<int> { 1, 3, 5 };
list.ForEach(x => Console.WriteLine(x));
Обновлено: черт возьми! Открытие визуальной студии для тестирования заняло слишком много времени.
Вы должны быть относительно младше - кому нужна Visual Studio? У меня в голове работает CLR. Дж / К
Другой подход, просто для удовольствия:
Console.WriteLine(string.Join("\t", list));
У меня это не работает со списком <int>. У меня InvalidCastException.
Я тоже получил InvalidCastException - ответ неверный. Более того, тот же результат, когда я пытался использовать List<CustomType> с неявным и явным преобразованием, реализованным для CustomType
Вам не нужно преобразовывать список в строку и преобразовывать в массив. string.Join примет список, поскольку существует перегрузка, которая принимает параметр IEnumerable <T>., как в IEnumerable (List) of <T> (в данном случае T = int), поэтому List будет повторяться и int.ToString ( ) будет вызываться в методе Join (). Console.WriteLine (string.Join ("\ t", список)); docs.microsoft.com/en-us/dotnet/api/…
public static void WriteLine(this List<int> theList)
{
foreach (int i in list)
{
Console.Write("{0}\t", t.ToString());
}
Console.WriteLine();
}
Тогда позже...
list.WriteLine();
new List<int> { 1, 3, 5 }.ForEach(Console.WriteLine);
Если есть фрагмент кода, который вы все время повторяете в соответствии с «Не повторять себя», вы должны поместить его в свою собственную библиотеку и вызвать его. Имея это в виду, есть два аспекта, чтобы получить правильный ответ. Во-первых, это ясность и краткость кода, вызывающего библиотечную функцию. Второй - влияние foreach на производительность.
Сначала подумаем о ясности и краткости вызывающего кода.
Вы можете выполнить foreach несколькими способами:
Из всех способов создания списка foreach List.ForEach с использованием lamba является самым ясным и кратким.
list.ForEach(i => Console.Write("{0}\t", i));
Таким образом, на данном этапе может показаться, что List.ForEach - лучший вариант. Однако какова производительность этого? Верно, что в этом случае время записи в консоль будет определять производительность кода. Когда мы знаем что-то о производительности той или иной языковой функции, мы должны, по крайней мере, это учитывать.
Согласно Измерения производительности foreach Дастоном Кэмпбеллом, самый быстрый способ перебора списка в оптимизированном коде - использовать цикл for без вызова List.Count.
Однако цикл for является многословной конструкцией. Это также рассматривается как очень итеративный способ делать что-то, что не соответствует текущей тенденции к функциональным идиомам.
Так можно ли добиться краткости, ясности и производительности? Мы можем использовать метод расширения. В идеале мы бы создали метод расширения на консоли, который берет список и записывает его с разделителем. Мы не можем этого сделать, потому что Console - это статический класс, а методы расширения работают только с экземплярами классов. Вместо этого нам нужно поместить метод расширения в сам список (согласно предложению Дэвида Б.):
public static void WriteLine(this List<int> theList)
{
foreach (int i in list)
{
Console.Write("{0}\t", t.ToString());
}
Console.WriteLine();
}
Этот код будет использоваться во многих местах, поэтому мы должны внести следующие улучшения:
Вот как будет выглядеть код функции:
public static void WriteToConsole<T>(this IList<T> collection)
{
int count = collection.Count();
for(int i = 0; i < count; ++i)
{
Console.Write("{0}\t", collection[i].ToString(), delimiter);
}
Console.WriteLine();
}
Мы можем улучшить это еще больше, разрешив клиенту передать разделитель. Затем мы могли бы предоставить вторую функцию, которая записывает на консоль со стандартным разделителем, например:
public static void WriteToConsole<T>(this IList<T> collection)
{
WriteToConsole<T>(collection, "\t");
}
public static void WriteToConsole<T>(this IList<T> collection, string delimiter)
{
int count = collection.Count();
for(int i = 0; i < count; ++i)
{
Console.Write("{0}{1}", collection[i].ToString(), delimiter);
}
Console.WriteLine();
}
Итак, теперь, учитывая, что нам нужен краткий, ясный и эффективный способ записи списков на консоль, он у нас есть. Вот весь исходный код, включая демонстрацию использования функции библиотеки:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleWritelineTest
{
public static class Extensions
{
public static void WriteToConsole<T>(this IList<T> collection)
{
WriteToConsole<T>(collection, "\t");
}
public static void WriteToConsole<T>(this IList<T> collection, string delimiter)
{
int count = collection.Count();
for(int i = 0; i < count; ++i)
{
Console.Write("{0}{1}", collection[i].ToString(), delimiter);
}
Console.WriteLine();
}
}
internal class Foo
{
override public string ToString()
{
return "FooClass";
}
}
internal class Program
{
static void Main(string[] args)
{
var myIntList = new List<int> {1, 2, 3, 4, 5};
var myDoubleList = new List<double> {1.1, 2.2, 3.3, 4.4};
var myDoubleArray = new Double[] {12.3, 12.4, 12.5, 12.6};
var myFooList = new List<Foo> {new Foo(), new Foo(), new Foo()};
// Using the standard delimiter /t
myIntList.WriteToConsole();
myDoubleList.WriteToConsole();
myDoubleArray.WriteToConsole();
myFooList.WriteToConsole();
// Using our own delimiter ~
myIntList.WriteToConsole("~");
Console.Read();
}
}
}
================================================== =====
Вы можете подумать, что это должен быть конец ответа. Однако можно сделать еще одно обобщение. Из вопроса fatcat непонятно, всегда ли он пишет в консоль. Возможно, в foreach нужно сделать что-то еще. В этом случае ответ Джейсона Бантинга даст эту общность. Вот его ответ еще раз:
list.ForEach(i => Console.Write("{0}\t", i));
Это если мы не сделаем еще одно уточнение наших методов расширения и не добавим FastForEach, как показано ниже:
public static void FastForEach<T>(this IList<T> collection, Action<T> actionToPerform)
{
int count = collection.Count();
for (int i = 0; i < count; ++i)
{
actionToPerform(collection[i]);
}
Console.WriteLine();
}
Это позволяет нам выполнять любой произвольный код для каждого элемента в коллекции используя максимально быстрый метод итерации.
Мы даже можем изменить функцию WriteToConsole, чтобы использовать FastForEach
public static void WriteToConsole<T>(this IList<T> collection, string delimiter)
{
collection.FastForEach(item => Console.Write("{0}{1}", item.ToString(), delimiter));
}
Итак, теперь весь исходный код, включая пример использования FastForEach:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleWritelineTest
{
public static class Extensions
{
public static void WriteToConsole<T>(this IList<T> collection)
{
WriteToConsole<T>(collection, "\t");
}
public static void WriteToConsole<T>(this IList<T> collection, string delimiter)
{
collection.FastForEach(item => Console.Write("{0}{1}", item.ToString(), delimiter));
}
public static void FastForEach<T>(this IList<T> collection, Action<T> actionToPerform)
{
int count = collection.Count();
for (int i = 0; i < count; ++i)
{
actionToPerform(collection[i]);
}
Console.WriteLine();
}
}
internal class Foo
{
override public string ToString()
{
return "FooClass";
}
}
internal class Program
{
static void Main(string[] args)
{
var myIntList = new List<int> {1, 2, 3, 4, 5};
var myDoubleList = new List<double> {1.1, 2.2, 3.3, 4.4};
var myDoubleArray = new Double[] {12.3, 12.4, 12.5, 12.6};
var myFooList = new List<Foo> {new Foo(), new Foo(), new Foo()};
// Using the standard delimiter /t
myIntList.WriteToConsole();
myDoubleList.WriteToConsole();
myDoubleArray.WriteToConsole();
myFooList.WriteToConsole();
// Using our own delimiter ~
myIntList.WriteToConsole("~");
// What if we want to write them to separate lines?
myIntList.FastForEach(item => Console.WriteLine(item.ToString()));
Console.Read();
}
}
}
Это действительно хороший ответ! Хотя мне не нравится идея иметь метод расширения, такой как WriteToConsole, в общем списке. Это явно нарушает модель единой ответственности. Я не ожидал, что список будет иметь какие-либо сведения о консоли, будь то ее реализация или метод расширения.
правда, я думаю, ваш выбор зависит от того, что вам нравится и какая забота важнее ...
Также вы можете присоединиться:
var qwe = new List<int> {5, 2, 3, 8};
Console.WriteLine(string.Join("\t", qwe));
Если в вашей среде нет
ForEach(как у меня), вы можете реализовать свой собственный.