【发布时间】:2011-06-20 12:31:03
【问题描述】:
我有一个包含许多值的对象,其中一些(不是对象中的所有值)需要放入CSV 字符串中。我的做法是这样的:
string csvString = o.number + "," + o.id + "," + o.whatever ....
有没有更好、更优雅的方式?
【问题讨论】:
-
一般来说,使用
+符号连接字符串被认为效率较低。它会创建更多要被垃圾收集的对象。
我有一个包含许多值的对象,其中一些(不是对象中的所有值)需要放入CSV 字符串中。我的做法是这样的:
string csvString = o.number + "," + o.id + "," + o.whatever ....
有没有更好、更优雅的方式?
【问题讨论】:
+ 符号连接字符串被认为效率较低。它会创建更多要被垃圾收集的对象。
如果将所有值放在一个数组中,至少可以使用string.Join。
string[] myValues = new string[] { ... };
string csvString = string.Join(",", myValues);
您还可以使用string.Join 的重载,它将params string 作为第二个参数,如下所示:
string csvString = string.Join(",", value1, value2, value3, ...);
【讨论】:
string.Join 使用参数数组。这意味着直接传递参数的代码将被编译器自动转换为使用数组。就开销而言,调用之间没有区别。
您可以覆盖对象的 ToString() 方法:
public override string ToString ()
{
return string.Format ("{0},{1},{2}", this.number, this.id, this.whatever);
}
【讨论】:
您可以使用string.Join 方法执行string.Join(",", o.Number, o.Id, o.whatever, ...) 之类的操作。
edit:正如 digEmAll 所说,string.Join 比 StringBuilder 快。他们对 string.Join 使用外部实现。
分析代码(当然在没有调试符号的版本中运行):
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
string r;
int iter = 10000;
string[] values = { "a", "b", "c", "d", "a little bit longer please", "one more time" };
sw.Restart();
for (int i = 0; i < iter; i++)
r = Program.StringJoin(",", values);
sw.Stop();
Console.WriteLine("string.Join ({0} times): {1}ms", iter, sw.ElapsedMilliseconds);
sw.Restart();
for (int i = 0; i < iter; i++)
r = Program.StringBuilderAppend(",", values);
sw.Stop();
Console.WriteLine("StringBuilder.Append ({0} times): {1}ms", iter, sw.ElapsedMilliseconds);
Console.ReadLine();
}
static string StringJoin(string seperator, params string[] values)
{
return string.Join(seperator, values);
}
static string StringBuilderAppend(string seperator, params string[] values)
{
StringBuilder builder = new StringBuilder();
builder.Append(values[0]);
for (int i = 1; i < values.Length; i++)
{
builder.Append(seperator);
builder.Append(values[i]);
}
return builder.ToString();
}
}
string.Join 在我的机器上用了 2 毫秒,而 StringBuilder.Append 用了 5 毫秒。所以有明显的区别。感谢 digAmAll 的提示。
【讨论】:
string.Join 和StringBuilder 一样快(如果不是稍微快一点的话),因为它们都只分配一个字符串
string.Join 的一个缺点(直到 .NET 4.0)是它需要一个字符串数组,如果你只有一个通用的 IEnumerable<string> 就强制你分配一个字符串...无论如何 .NET 4.0已解决此问题
如果您使用的是 .NET 4,则可以使用 string.Join 的重载,如果您也将它们放在 List 中,则它需要一个 IEnumerable:
string.Join(", ", strings);
【讨论】:
另一种方法是使用 System.Configuration 命名空间/程序集中的 CommaDelimitedStringCollection 类。它的行为类似于一个列表,而且它有一个重写的 ToString 方法,该方法返回一个逗号分隔的字符串。
优点 - 比数组更灵活。
缺点 - 您不能传递包含逗号的字符串。
CommaDelimitedStringCollection list = new CommaDelimitedStringCollection();
list.AddRange(new string[] { "Huey", "Dewey" });
list.Add("Louie");
//list.Add(",");
string s = list.ToString(); //Huey,Dewey,Louie
【讨论】: