Console.WriteLine og generisk liste

Console.WriteLine og generisk liste

Gør dette:

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

EDIT:Til andre, der har svaret - han vil have dem alle på samme linje, med faner imellem dem. :)


En anden tilgang, bare for kick:

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

Hvis der er et stykke kode, som du gentager hele tiden ifølge Don't Repeat Yourself, skal du lægge det i dit eget bibliotek og kalde det. Med det i tankerne er der 2 aspekter til at få det rigtige svar her. Den første er klarhed og korthed i koden, der kalder biblioteksfunktionen. Den anden er præstationsimplikationerne af foreach.

Lad os først tænke på klarheden og kortheden i opkaldskoden.

Du kan gøre foreaching på en række måder:

  1. for loop
  2. foreach loop
  3. Samling.ForHver

Ud af alle måder at lave en foreach liste på. For hver med en lamba er den klareste og korteste.

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

Så på dette tidspunkt kan det se ud til, at Listen.ForEach er vejen at gå. Men hvad er ydeevnen af ​​dette? Det er rigtigt, at i dette tilfælde vil tiden til at skrive til konsollen styre kodens ydeevne. Når vi ved noget om ydeevnen af ​​en bestemt sprogfunktion, bør vi bestemt i det mindste overveje det.

Ifølge Duston Campbells præstationsmålinger af foreach er den hurtigste måde at gentage listen under optimeret kode på at bruge en for-løkke uden et kald til List.Count.

For-løkken er imidlertid en verbose konstruktion. Det ses også som en meget iterativ måde at gøre ting på, som ikke stemmer overens med den nuværende tendens til funktionelle idiomer.

Så kan vi få korthed, klarhed og ydeevne? Det kan vi ved at bruge en udvidelsesmetode. I en ideel verden ville vi oprette en udvidelsesmetode på konsollen, der tager en liste og skriver den med en afgrænser. Vi kan ikke gøre dette, fordi Console er en statisk klasse, og udvidelsesmetoder virker kun på forekomster af klasser. I stedet skal vi sætte udvidelsesmetoden på selve listen (som ifølge David B's forslag):

public static void WriteLine(this List<int> theList)
{
  foreach (int i in list)
  {
    Console.Write("{0}\t", t.ToString());
  }
  Console.WriteLine();
}

Denne kode kommer til at blive brugt mange steder, så vi bør udføre følgende forbedringer:

  • I stedet for at bruge foreach bør vi bruge den hurtigste måde at iterere samlingen på, som er en for-løkke med et cachetal.
  • I øjeblikket kan kun List sendes som et argument. Som en biblioteksfunktion kan vi generalisere den gennem en lille indsats.
  • Brug af List begrænser os til kun lister. Ved at bruge IList kan denne kode også arbejde med arrays.
  • Da udvidelsesmetoden vil være på en IList, er vi nødt til at ændre navnet for at gøre det tydeligere, hvad vi skriver til:

Sådan ser koden til funktionen ud:

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

Vi kan forbedre dette yderligere ved at lade klienten passere afgrænseren. Vi kunne så give en anden funktion, der skriver til konsollen med standardafgrænseren som denne:

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

Så nu, da vi ønsker en kort, klar og effektiv måde at skrive lister til konsollen på, har vi en. Her er hele kildekoden inklusive en demonstration af brugen af ​​biblioteksfunktionen:

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

========================================================

Du tror måske, at dette burde være slutningen på svaret. Der er dog endnu et stykke generalisering, der kan gøres. Det fremgår ikke klart af fatcats spørgsmål, om han altid skriver til konsollen. Måske skal der gøres noget andet i forgrunden. I så fald vil Jason Buntings svar give den almene karakter. Her er hans svar igen:

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

Det er, medmindre vi foretager endnu en forbedring af vores udvidelsesmetoder og tilføjer FastForEach som nedenfor:

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

Dette giver os mulighed for at udføre enhver vilkårlig kode mod hvert element i samlingen ved at bruge den hurtigst mulige iterationsmetode .

Vi kan endda ændre WriteToConsole-funktionen til at bruge FastForEach

public static void WriteToConsole<T>(this IList<T> collection, string delimiter)
{
     collection.FastForEach(item => Console.Write("{0}{1}", item.ToString(), delimiter));
}

Så nu er hele kildekoden, inklusive et eksempel på brug af 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();
        }
    }
}