Console.WriteLine和通用列表

时间:2020-03-05 18:50:21  来源:igfitidea点击:

我经常发现自己在编写这样的代码:

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对其进行测试。

回答

另一种方法,仅用于踢球:

Console.WriteLine(string.Join("\t", list.Cast<string>().ToArray()));

回答

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

然后,以后...

list.WriteLine();

回答

新列表{1,3,5} .ForEach(Console.WriteLine);

回答

如果有部分代码根据"不要重复自己"的规定一直重复执行,则应将其放在自己的库中并进行调用。考虑到这一点,有两个方面可以在此处获得正确的答案。首先是调用库函数的代码的简洁明了。第二个是foreach对性能的影响。

首先,让我们考虑一下调用代码的清晰度和简洁性。

我们可以通过多种方式进行foreach:

  • for循环
  • foreach循环
  • 收集每个

用所有方法创建一个foreach列表。用兰巴(Lamba)进行的ForEach最清晰,最简短。

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

因此,在此阶段可能看起来像List.ForEach是要走的路。但是,这有什么表现呢?的确,在这种情况下,写入控制台的时间将控制代码的性能。当我们对特定语言功能的性能有所了解时,我们当然至少应该考虑一下。

根据Duston Campbell对foreach的性能测量,在优化代码下迭代列表的最快方法是使用for循环而不调用List.Count。

但是,for循环是冗长的构造。它也被视为一种非常迭代的方式,与当前的功能习惯用法趋势不符。

那么我们能否简洁明了,表现出色?我们可以通过使用扩展方法。在理想的情况下,我们将在Console上创建一个扩展方法,该方法接受一个列表并用定界符将其写入。我们不能这样做,因为Console是静态类,而扩展方法仅适用于类的实例。相反,我们需要将扩展​​方法放在列表本身上(根据David B的建议):

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的问题尚不清楚他是否一直在写控制台。也许在前言中还有其他事情要做。在那种情况下,Jason Bunting的答案将给出一般性。这又是他的答案:

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