Console.WriteLine() vs. Console.WriteLine(string.Empty)
本文关键字:Console WriteLine Empty vs string | 更新日期: 2023-09-27 17:57:30
在我们的一个应用程序中,我遇到了一些类似的行:
Console.WriteLine(string.Empty);
我检查了如果我只写是否有什么不同
Console.WriteLine();
但是输出是一样的(正如预期的)。
这个例子中的"最佳实践"是什么?是否存在需要传递空string
而不是不传递任何参数的情况?
WriteLine()
是这样实现的:
public virtual void WriteLine() {
Write(CoreNewLine);
}
然而,WriteLine(string)
是这样实现的:
public virtual void WriteLine(String value) {
if (value==null) {
WriteLine();
}
else {
// We'd ideally like WriteLine to be atomic, in that one call
// to WriteLine equals one call to the OS (ie, so writing to
// console while simultaneously calling printf will guarantee we
// write out a string and new line chars, without any interference).
// Additionally, we need to call ToCharArray on Strings anyways,
// so allocating a char[] here isn't any worse than what we were
// doing anyways. We do reduce the number of calls to the
// backing store this way, potentially.
int vLen = value.Length;
int nlLen = CoreNewLine.Length;
char[] chars = new char[vLen+nlLen];
value.CopyTo(0, chars, 0, vLen);
// CoreNewLine will almost always be 2 chars, and possibly 1.
if (nlLen == 2) {
chars[vLen] = CoreNewLine[0];
chars[vLen+1] = CoreNewLine[1];
}
else if (nlLen == 1)
chars[vLen] = CoreNewLine[0];
else
Buffer.InternalBlockCopy(CoreNewLine, 0, chars, vLen * 2, nlLen * 2);
Write(chars, 0, vLen + nlLen);
}
}
如果使用null
字符串调用它,则会得到与不带参数的WriteLine()
相同的结果(外加一个额外的方法调用)。然而,传递非空字符串时的逻辑有点复杂。
对于string.Empty
,这将分配一个长度为2的新字符数组,并将新行字符复制到该数组中。
这通常不贵,但如果你不想打印任何东西,仍然有点多余。特别是对于固定的对Console.WriteLine
的调用,将string.Empty
传递到那里没有任何意义。
如果只是为了简单起见,您应该更喜欢Console.WriteLine()
而不是Console.WriteLine(string.Empty)
。
最佳实践是使用可读性更强的Console.WriteLine();
。
即使没有语义差异,如果编写Console.WriteLine(string.Empty);
:,也会执行不必要的代码
public virtual void WriteLine(String value) {
if (value==null) {
WriteLine();
}
else {
// We'd ideally like WriteLine to be atomic, in that one call
// to WriteLine equals one call to the OS (ie, so writing to
// console while simultaneously calling printf will guarantee we
// write out a string and new line chars, without any interference).
// Additionally, we need to call ToCharArray on Strings anyways,
// so allocating a char[] here isn't any worse than what we were
// doing anyways. We do reduce the number of calls to the
// backing store this way, potentially.
int vLen = value.Length;
int nlLen = CoreNewLine.Length;
char[] chars = new char[vLen+nlLen];
value.CopyTo(0, chars, 0, vLen);
// CoreNewLine will almost always be 2 chars, and possibly 1.
if (nlLen == 2) {
chars[vLen] = CoreNewLine[0];
chars[vLen+1] = CoreNewLine[1];
}
else if (nlLen == 1)
chars[vLen] = CoreNewLine[0];
else
Buffer.InternalBlockCopy(CoreNewLine, 0, chars, vLen * 2, nlLen * 2);
Write(chars, 0, vLen + nlLen);
}
/*
Write(value); // We could call Write(String) on StreamWriter...
WriteLine();
*/
}
里面有一个缓冲区分配和字符串复制如果他们写了if (string.IsNullOrEmpty(value))
会更好,但由于某种原因,他们没有。
而更简单的方法只是:
public virtual void WriteLine() {
Write(CoreNewLine);
}
(CoreNewLine
是char[]
)
在技术方面对我来说没有任何区别。这正是开发人员发现它更舒适、更可读的方式。对我来说,Console.WriteLine()
更直观的是它在写一行空行,而Console.WriteLine(String.Empty)
让我停下来思考一秒钟(也许更少)。
IMO认为,任何其他变体都是一种让代码变得花哨的行为,不应用于专业生产代码。
来自引用(https://msdn.microsoft.com/en-us/library/system.console.writeline(v=vs.110).aspx)
WriteLine(字符串):将指定的字符串值,后跟当前行终止符,写入标准输出流。
WriteLine():将当前行终止符写入标准输出流。
它似乎完全没有(视觉)差异(正如另一个答案所提到的,实现是另一回事),并且取决于用户偏好,尽管我不确定我认识多少人喜欢不必要的代码。
正如您在tryroslyn 上看到的那样
C#代码:
using System;
public class C {
public void M() {
Console.WriteLine();
Console.WriteLine(String.Empty);
}
}
生成IL代码:
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class public auto ansi beforefieldinit C
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig
instance void M () cil managed
{
// Method begins at RVA 0x2050
// Code size 19 (0x13)
.maxstack 8
IL_0000: nop
IL_0001: call void [mscorlib]System.Console::WriteLine()
IL_0006: nop
IL_0007: ldsfld string [mscorlib]System.String::Empty
IL_000c: call void [mscorlib]System.Console::WriteLine(string)
IL_0011: nop
IL_0012: ret
} // end of method C::M
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2064
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method C::.ctor
} // end of class C
所以第Console.WriteLine(String.Empty);
行从string.Empty
中获取值并将其传递给函数。最好是Console.WriteLine()
更少的操作。