事实上,您的代码做了一些基本非常功能的事情,即它通过连接列表项将字符串列表减少为单个字符串。关于代码唯一必要的事情是使用StringBuilder。
实际上,函数式代码使这变得更容易,因为它不需要像您的代码那样的特殊情况。更好的是,.NET 已经已经实现了这个特定的操作,并且可能比你的代码更有效1):
return String.Join(", ", ListOfResources.Select(s => s.Id.ToString()).ToArray());
(是的,对ToArray() 的调用很烦人,但Join 是一种非常古老的方法并且早于LINQ。)
当然,Join 的“更好”版本可以这样使用:
return ListOfResources.Select(s => s.Id).Join(", ");
实现相当简单——但再一次,使用StringBuilder(为了性能)使其变得势在必行。
public static String Join<T>(this IEnumerable<T> items, String delimiter) {
if (items == null)
throw new ArgumentNullException("items");
if (delimiter == null)
throw new ArgumentNullException("delimiter");
var strings = items.Select(item => item.ToString()).ToList();
if (strings.Count == 0)
return string.Empty;
int length = strings.Sum(str => str.Length) +
delimiter.Length * (strings.Count - 1);
var result = new StringBuilder(length);
bool first = true;
foreach (string str in strings) {
if (first)
first = false;
else
result.Append(delimiter);
result.Append(str);
}
return result.ToString();
}
1) 在没有查看反射器中的实现的情况下,我猜String.Join 第一次遍历字符串以确定总长度。这可用于相应地初始化StringBuilder,从而节省以后昂贵的复制操作。
由 SLaks 编辑:这是来自 .Net 3.5 的 String.Join 相关部分的参考来源:
string jointString = FastAllocateString( jointLength );
fixed (char * pointerToJointString = &jointString.m_firstChar) {
UnSafeCharBuffer charBuffer = new UnSafeCharBuffer( pointerToJointString, jointLength);
// Append the first string first and then append each following string prefixed by the separator.
charBuffer.AppendString( value[startIndex] );
for (int stringToJoinIndex = startIndex + 1; stringToJoinIndex <= endIndex; stringToJoinIndex++) {
charBuffer.AppendString( separator );
charBuffer.AppendString( value[stringToJoinIndex] );
}
BCLDebug.Assert(*(pointerToJointString + charBuffer.Length) == '\0', "String must be null-terminated!");
}