C#7:Out 变量中的下划线 (_) 和星号 (*)
C#7: Underscore ( _ ) & Star ( * ) in Out variable
我正在阅读 C#7 here 中新的输出变量功能。我有两个问题:
它说
We allow "discards" as out parameters as well, in the form of a _
, to let you ignore out parameters you don’t care about:
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 的疏忽?
关于第一个问题
I guess this is just an info and not a new feature of C#7 because we can
do so in pre C#7.0 too.
var _;
if (Int.TryParse(str, out _))
// ...
新颖之处在于您不必再在表达式内部或外部声明 _
,您只需键入
int.TryParse(s, out _);
尝试在 C#7 之前完成这一行:
private void btnDialogOk_Click_1(object sender, RoutedEventArgs e)
{
DialogResult = int.TryParse(Answer, out _);
}
更好奇
考虑以下片段
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 所指出的,很酷的一点是您不必预先声明 变量,如果您对某些值不感兴趣,这会很方便。
Discards,在 C#7 中,可以在声明变量的任何地方使用,以 - 顾名思义 - 丢弃结果。所以丢弃可以与out变量一起使用:
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
例外情况是 _
变量用作输出变量。在这种情况下,编译器会忽略类型或 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。
C# 7 中丢弃运算符 _
的另一个示例是 pattern match switch
语句中类型 object
的变量,这是最近在 C# 中添加的7:
代码:
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.0(Visual Studio 2017 年 2017 年 3 月左右)中,在以下上下文中支持丢弃赋值:
- 元组和对象解构。
- Pattern matching with is and switch.
- 调用不带参数的方法。
- 范围内没有 _ 时的独立 _。
其他有用的笔记
- 丢弃可以减少内存分配。因为他们立意
你的代码清晰,它们增强了它的可读性和可维护性
- 请注意,_ 也是一个有效的标识符。在外部使用时
支持的上下文
简单的例子:这里我们不想使用第一个和第二个参数,只需要第三个参数
(_, _, area) = city.GetCityInformation(cityName);
switch case 中的高级示例,它也使用了现代 switch case 模式匹配 (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;
}
Q: ... we can do so in pre C#7.0 too:
var _;
if (Int.TryParse(str, out _))
or am I missing something here?
那不是一回事。
您的代码正在赋值。
在 C# 7.0 中 _ 不是 变量,它告诉编译器丢弃值
(除非你已经声明了_作为一个变量...如果你这样做了变量被使用而不是丢弃符号)
示例:您可以在 同一行代码中使用 _ 作为 sting 和 int :
string a;
int b;
Test(out a, out b);
Test(out _, out _);
//...
void Test(out string a, out int b)
{
//...
}
我正在阅读 C#7 here 中新的输出变量功能。我有两个问题:
它说
We allow "discards" as out parameters as well, in the form of a
_
, to let you ignore out parameters you don’t care about: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 的疏忽?
关于第一个问题
I guess this is just an info and not a new feature of C#7 because we can do so in pre C#7.0 too.
var _; if (Int.TryParse(str, out _)) // ...
新颖之处在于您不必再在表达式内部或外部声明 _
,您只需键入
int.TryParse(s, out _);
尝试在 C#7 之前完成这一行:
private void btnDialogOk_Click_1(object sender, RoutedEventArgs e)
{
DialogResult = int.TryParse(Answer, out _);
}
更好奇
考虑以下片段
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 所指出的,很酷的一点是您不必预先声明 变量,如果您对某些值不感兴趣,这会很方便。
Discards,在 C#7 中,可以在声明变量的任何地方使用,以 - 顾名思义 - 丢弃结果。所以丢弃可以与out变量一起使用:
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
例外情况是 _
变量用作输出变量。在这种情况下,编译器会忽略类型或 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。
C# 7 中丢弃运算符 _
的另一个示例是 pattern match switch
语句中类型 object
的变量,这是最近在 C# 中添加的7:
代码:
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.0(Visual Studio 2017 年 2017 年 3 月左右)中,在以下上下文中支持丢弃赋值:
- 元组和对象解构。
- Pattern matching with is and switch.
- 调用不带参数的方法。
- 范围内没有 _ 时的独立 _。
其他有用的笔记
- 丢弃可以减少内存分配。因为他们立意 你的代码清晰,它们增强了它的可读性和可维护性
- 请注意,_ 也是一个有效的标识符。在外部使用时 支持的上下文
简单的例子:这里我们不想使用第一个和第二个参数,只需要第三个参数
(_, _, area) = city.GetCityInformation(cityName);
switch case 中的高级示例,它也使用了现代 switch case 模式匹配 (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;
}
Q: ... we can do so in pre C#7.0 too:
var _;
if (Int.TryParse(str, out _))
or am I missing something here?
那不是一回事。
您的代码正在赋值。
在 C# 7.0 中 _ 不是 变量,它告诉编译器丢弃值
(除非你已经声明了_作为一个变量...如果你这样做了变量被使用而不是丢弃符号)
示例:您可以在 同一行代码中使用 _ 作为 sting 和 int :
string a;
int b;
Test(out a, out b);
Test(out _, out _);
//...
void Test(out string a, out int b)
{
//...
}