C#7:下划线(_)& Out变量中的星号(*)

时间:2017-03-21 07:20:10

标签: c# c#-7.0

我正在阅读C#7中here的新变量功能。我有两个问题:

  1. 它说

      

    我们允许"丢弃"作为out参数,以_的形式,让你忽略你不关心的参数:

    p.GetCoordinates(out var x, out _); // I only care about x
    

    问:我想这只是一个信息,而不是C#7的新功能,因为我们也可以在C#7.0之前这样做:

    var _;
    if (Int.TryParse(str, out _))
    ...
    

    或者我在这里遗漏了什么?

  2. 当我在同一个博客中提及时,我的代码会出错:

    ~Person() => names.TryRemove(id, out *);
    

    *不是有效的标识符。 Mads Torgersen疏忽我猜?

6 个答案:

答案 0 :(得分:88)

在p#7中的

Discards可以在声明变量的任何地方使用,顾名思义 - 丢弃结果。因此丢弃可以与变量一起使用:

p.GetCoordinates(out var x, out _);

,它可以用来丢弃表达式结果:

_ = 42;

在示例中,

p.GetCoordinates(out var x, out _);
_ = 42;

没有引入变量_。只有两种使用丢弃的情况。

但是,如果范围中存在标识符_,则无法使用丢弃:

var _ = 42;
_ = "hello"; // error - a string cannot explicitly convert from string to int

例外情况是将_变量用作out变量。在这种情况下,编译器会忽略类型或var并将其视为丢弃:

if (p.GetCoordinates(out double x, out double _))
{
    _ = "hello"; // works fine.
    Console.WriteLine(_); // error: _ doesn't exist in this context.
}

请注意,只有在使用out var _out double _时才会出现这种情况。只需使用out _,然后将其视为对现有变量_的引用,如果它在范围内,例如:

string _;
int.TryParse("1", out _); // complains _ is of the wrong type

最后,在有关丢弃物的讨论的早期but was abandoned in favour of _ due to the latter being a more commonly used notation in other languages提出了*符号。

答案 1 :(得分:18)

C#7中丢弃运算符switch的另一个示例是pattern match static void Main(string[] args) { object x = 6.4; switch (x) { case string _: Console.WriteLine("it is string"); break; case double _: Console.WriteLine("it is double"); break; case int _: Console.WriteLine("it is int"); break; default: Console.WriteLine("it is Unknown type"); break; } // end of main method } 语句中case ... _类型的变量,该变量最近在C#7中添加:

<强>代码:

{{1}}

此代码将匹配类型并丢弃传递给{{1}}的变量。

答案 2 :(得分:11)

更好奇的

考虑以下代码段

static void Main(string[] args)
{
    //....
    int a;
    int b;

    Test(out a, out b);
    Test(out _, out _);    
    //....
}

private static void Test(out int a, out int b)
{
    //...
}

这就是发生的事情:

...

13:             int  a;
14:             int  b;
15: 
16:             Test(out a, out b);
02340473  lea         ecx,[ebp-40h]  
02340476  lea         edx,[ebp-44h]  
02340479  call        02340040  
0234047E  nop  
    17:             Test(out _, out _);
0234047F  lea         ecx,[ebp-48h]  
02340482  lea         edx,[ebp-4Ch]  
02340485  call        02340040  
0234048A  nop 

...

正如你在幕后看到的那样,两个电话正在做同样的事情。

正如@ServéLaurijssen所指出的那样,很酷的事情是你没有预先声明变量,如果你对某些值不感兴趣,这些变量很方便。

答案 3 :(得分:8)

关于第一个问题

  

我想这只是一个信息而不是C#7的新功能,因为我们可以   在C#7.0之前也这样做。

Z

新颖之处在于你不必再在表达式内外声明var _; if (Int.TryParse(str, out _)) // ... ,只需输入

即可。
_

尝试在C#7之前做一个班轮:

int.TryParse(s, out _);

答案 4 :(得分:0)

在C#7.0(大约在2017年3月的Visual Studio 2017中)中,在以下情况下分配中支持丢弃:


其他有用的笔记

  • 丢弃可以减少内存分配。因为他们表达了意图 清晰的代码,它们提高了可读性和可维护性
  • 请注意,_也是有效的标识符。当在 支持的上下文

简单的例子:这里我们不想使用第一和第二参数,而只需要第三参数

(_, _, area) = city.GetCityInformation(cityName);

开关盒的高级示例,它也使用了现代的开关盒模式匹配(source

switch (exception)                {
case ExceptionCustom exceptionCustom:       
        //do something unique
        //...
    break;
case OperationCanceledException _:
    //do something else here and we can also cast it 
    //...
    break;
default:
    logger?.Error(exception.Message, exception);
    //..
    break;

}

答案 5 :(得分:0)

  

Q:...我们也可以在C#7.0之前的版本中这样做:

var _;
if (Int.TryParse(str, out _))
  

还是我在这里想念什么?

那不是同一回事。
您的代码正在分配。

在C#7.0中_ 不是变量,它告诉编译器放弃该值
除非 ,您已将 _ 声明为变量...如果您这样做是使用变量而不是丢弃符​​号)

示例:您可以将 _ 用作字符串,并在同一行代码中插入int

string a; 
int b;
Test(out a, out b);
Test(out _, out _);

//...

void Test(out string a, out int b)
{
   //...
}