我正在阅读C#7中here的新变量功能。我有两个问题:
它说
我们允许"丢弃"作为out参数,以
_
的形式,让你忽略你不关心的参数:p.GetCoordinates(out var x, out _); // I only care about x
问:我想这只是一个信息,而不是C#7的新功能,因为我们也可以在C#7.0之前这样做:
var _;
if (Int.TryParse(str, out _))
...
或者我在这里遗漏了什么?
当我在同一个博客中提及时,我的代码会出错:
~Person() => names.TryRemove(id, out *);
*
不是有效的标识符。 Mads Torgersen疏忽我猜?
答案 0 :(得分:88)
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)
{
//...
}