如果有一段代码根据“不要重复自己”一直重复,那么应该把它放在自己的库中并调用它。考虑到这一点,在这里得到正确答案有两个方面。首先是调用库函数的代码中的清晰和简洁。其次是foreach的性能影响。
首先让我们考虑调用代码的清晰度和简洁性。
您可以在许多方面做的foreach:
- for循环
- foreach循环
- Collection.ForEach
超出了所有做一个foreach列表的方式。对于每个与兰巴是最清楚和最简单的。
list.ForEach(i => Console.Write("{0}\t", i));
所以在这个阶段它可能看起来像List.ForEach是要走的路。然而,这是什么表现?确实,在这种情况下写入控制台的时间将决定代码的性能。当我们知道一些特定语言特性的表现时,我们当然应该至少考虑它。
根据Duston Campbell's performance measurements of foreach在优化代码下迭代列表的最快方法是使用for循环,而不调用List.Count。
但for循环是一个详细的构造。它也被认为是一种非常反复的做法,与目前的功能性习语趋势不匹配。
所以我们可以得到简洁,清晰和性能?我们可以通过使用扩展方法。在理想的世界中,我们将在控制台上创建一个扩展方法,该方法需要一个列表并用分隔符写入。我们不能这样做,因为控制台是一个静态类,扩展方法只适用于类的实例。相反,我们需要把列表本身的扩展方法(按照大卫·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();
}
}
}
击败你大约30秒。 :) – 2008-09-09 21:23:53