Console.WriteLine и общий список

Я часто пишу такой код:

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);

Я подозреваю, что есть какой-нибудь хитрый способ сделать это, но я этого не вижу. Есть ли у кого-нибудь лучшее решение, чем первый блок?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
42
0
112 463
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Ответ принят как подходящий

Сделай это:

list.ForEach(i => Console.Write("{0}\t", i));

Обновлено: для других, кто ответил - он хочет, чтобы все они были в одной строке с вкладками между ними. :)

Если в вашей среде нет ForEach (как у меня), вы можете реализовать свой собственный.

testing 25.02.2019 18:40

        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. Дж / К

Jason Bunting 10.09.2008 01:42

Другой подход, просто для удовольствия:

Console.WriteLine(string.Join("\t", list));

У меня это не работает со списком <int>. У меня InvalidCastException.

Setyo N 28.06.2013 06:51

Я тоже получил InvalidCastException - ответ неверный. Более того, тот же результат, когда я пытался использовать List<CustomType> с неявным и явным преобразованием, реализованным для CustomType

sergtk 19.12.2013 04:45

Вам не нужно преобразовывать список в строку и преобразовывать в массив. 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/…

Antony Booth 22.05.2019 22:10

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 несколькими способами:

  1. для цикла
  2. цикл foreach
  3. Collection.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();
}

Этот код будет использоваться во многих местах, поэтому мы должны внести следующие улучшения:

  • Вместо использования foreach мы должны использовать самый быстрый способ итерации коллекции, который представляет собой цикл for с кешированным счетчиком.
  • В настоящее время в качестве аргумента можно передавать только список. Как библиотечную функцию мы можем обобщить ее, приложив небольшие усилия.
  • Использование List ограничивает нас только списками, использование IList позволяет этому коду также работать с массивами.
  • Поскольку метод расширения будет в списке IList, нам нужно изменить имя, чтобы было понятнее, что мы пишем:

Вот как будет выглядеть код функции:

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, в общем списке. Это явно нарушает модель единой ответственности. Я не ожидал, что список будет иметь какие-либо сведения о консоли, будь то ее реализация или метод расширения.

Florian Greinacher 29.09.2011 17:32

правда, я думаю, ваш выбор зависит от того, что вам нравится и какая забота важнее ...

Ed Sykes 07.08.2012 18:47

Также вы можете присоединиться:

var qwe = new List<int> {5, 2, 3, 8};
Console.WriteLine(string.Join("\t", qwe));

Другие вопросы по теме