仅限C#变量名称"_"(下划线)

Sam*_*amy 20 c# naming-conventions identifier

我只是在C#中遇到了一个小问题,它只是一个复制粘贴错误,但不知道C#如何接受它.

这段代码成功编译......怎么样

namespace DemoNS
{
    class DemoClass
    {
        String _ = new String('a', 1);        
    }
}
Run Code Online (Sandbox Code Playgroud)

名为变量的默认值是什么_

svi*_*ick 39

不,没有默认意义,_只是一个变量名称,就像任何其他名称一样.

我喜欢以与Prolog的匿名变量类似的方式使用它:当你创建一个忽略其中一个参数的lambda时,你可以命名它_:

EventHandler handler = (_, e) => Console.WriteLine(e);
Run Code Online (Sandbox Code Playgroud)

另一方面,我不会在其他地方使用它,你应该使用描述性名称.

编辑:请注意,在C#7.0中,_有时具有特殊含义.例如,_ = new String('a', 1);即使您没有声明名为的变量,也可以编写_.

  • lambda中的惯用语,你不关心一个论点. (24认同)
  • 但请注意:不要使用它. (13认同)
  • 作为参考(虽然有点过时)这里是标识符规范:http://msdn.microsoft.com/en-us/library/aa664670.aspx (2认同)
  • 当您不关心参数/参数/值时,Underscore在Python中也是惯用的. (2认同)

Mot*_*ohn 38

现在有了C#7.0,_它确实有时具有重要意义.它成为新功能的丢弃运营商out var.它在函数返回值时使用,并且您希望通知编译器您不会使用它 - 因此可以对其进行优化.或者在解构(另一个C#7.0功能)时,您可以使用它来忽略您不感兴趣的元组的一部分.

例如 出变种

void Test(out int i) => i = 1;

Test(out _); // _ was never declared, it will still compile in C# 7.0

var r = _;   // error CS0103: The name '_' does not exist in the current context
Run Code Online (Sandbox Code Playgroud)

解构元组的示例

var Person = ("John", "Smith");

var (First, _) = Person; // '_' is not a declared

Debug.Print(First); // prints "John"
Debug.Print(_); // error CS0103: The name '_' does not exist in the current context
Run Code Online (Sandbox Code Playgroud)

如果您声明自己的变量名称_然后使用discard运算符会导致歧义,则会出现问题.此问题已在此处报道.

编辑 上面的问题不是问题,因为@ maf-soft在评论中指出.如果_声明它被视为常规变量,就像它在C#7.0之前一样.


Oli*_*isz 20

前面的答案都很有用,但我认为他们错过了一个用例。如果您不想使用函数的返回值,可以使用该_字符,即:

代替

int returnvalue = RandomFunction();
Run Code Online (Sandbox Code Playgroud)

你可以做

_ = RandomFunction();
Run Code Online (Sandbox Code Playgroud)

  • 从技术上讲,它做同样的事情,但明确标记您不想使用返回值 1) 创建更干净的代码,2) 告诉 IDE 您是故意这样做的,因此您不会收到警告。 (12认同)
  • 与“RandomFunction();”相比,“_ = RandomFunction();”有什么好处(即根本不分配返回值)? (7认同)

Bue*_*ler 5

_是一个与aor 相同的有效字符,i并且语法变量可以从这里开始,_因此单个字符名称在_语法上是完全正确的.不是一个非常好的选择,但将编译和工作正常.


Lak*_*ran 5

它是一个丢弃变量,它是一个占位符变量并且未使用。它告诉编译器对输出值不感兴趣。 示例:创建一个文件处理类。构造函数将启动该过程。并且,我们有复制、删除操作。假设,一个特定的类有责任启动该进程,但无需担心其他操作。然后我会声明像_ = new FileListener(); 我不会担心输出。其他类可以实例化FileListener obj = new FileListener(); 或者可以调用其他操作作为FileListener.CopyFile()

样本:

    class Program
        {
            static void Main(string[] args)
            {
   /// Ignore the instance value but initialized the operation by instantiation
                _ = new FileListener();
                
                Console.WriteLine("Hello World!");
            }
        }
        
        public class FileListener 
        {
            public FileListener()
            {
                /// Logic to listen external file changes
            }
            public static void DeleteFile()
            { }
            public static void CopyFile()
            { }
        }
Run Code Online (Sandbox Code Playgroud)