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而不是不传递任何参数的情况?

Console.WriteLine() vs. Console.WriteLine(string.Empty)

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

CoreNewLinechar[]

在技术方面对我来说没有任何区别。这正是开发人员发现它更舒适、更可读的方式。对我来说,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()更少的操作。