C # 7: Subrayado () y Estrella ( * ) en la variable Out
Estaba leyendo sobre nuevas características variables en C#7 aquí. Tengo dos preguntas:
-
Dice:
También permitimos "descartes" como parámetros de salida, en forma de
_
, para permitirle ignorar los parámetros que no le importan:p.GetCoordinates(out var x, out _); // I only care about x
P: Supongo que esto es solo una información y no una nueva característica de C # 7 porque también podemos hacerlo en pre C # 7.0:
var _; if (Int.TryParse(str, out _)) ...
O me estoy perdiendo algo aquí?
-
Mi código da un error cuando lo hago como se menciona en el mismo blog:
~Person() => names.TryRemove(id, out *);
*
no es un identificador válido. Un descuido de Mads Torgersen, supongo.
4 answers
Los descartes, en C#7 se pueden usar donde se declare una variable, para - como su nombre indica - descartar el resultado. Por lo tanto, se puede usar sin variables:
p.GetCoordinates(out var x, out _);
Y se puede usar para descartar un resultado de expresión:
_ = 42;
En el ejemplo,
p.GetCoordinates(out var x, out _);
_ = 42;
No se introduce ninguna variable, _
. Solo hay dos casos de un descarte que se está utilizando.
Sin embargo, si existe un identificador _
en el ámbito, entonces los descartes no pueden ser usado:
var _ = 42;
_ = "hello"; // error - a string cannot explicitly convert from string to int
La excepción a esto es cuando una variable _
se usa como una variable out. En este caso, el compilador ignora el tipo o var
y lo trata como un descarte:
if (p.GetCoordinates(out double x, out double _))
{
_ = "hello"; // works fine.
Console.WriteLine(_); // error: _ doesn't exist in this context.
}
Tenga en cuenta que esto solo ocurre si, en este caso, se usa out var _
o out double _
. Simplemente use out _
y luego se trata como una referencia a una variable existente, _
, si está en el alcance, por ejemplo:
string _;
int.TryParse("1", out _); // complains _ is of the wrong type
Finalmente, la notación *
se propuso al principio de las discusiones sobre los descartes, pero fue abandonado a favor de _
debido a que este último es una notación más utilizada en otros idiomas .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-27 12:33:44
Para más curiosos
Considere el siguiente fragmento
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)
{
//...
}
Esto es lo que está sucediendo:
...
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
...
Como se puede ver detrás de la escena las dos llamadas están haciendo lo mismo.
Como @Servé Laurijssen señaló, lo bueno es que no tienes que pre-declarar variables, lo cual es útil si no estás interesado en algunos valores.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-21 11:03:23
Otro ejemplo del Operador de descarte _
en C # 7 es pattern match una variable de tipo object
en una instrucción switch
, que se agregó recientemente en C # 7:
Código:
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
}
Este código coincidirá con el tipo y descartará la variable pasada a case ... _
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-27 12:37:37
Sobre la primera cuestión
Supongo que esto es solo una información y no una nueva característica de C#7 porque podemos hazlo también en pre C # 7.0.
var _; if (Int.TryParse(str, out _)) // ...
La novedad es que ya no tienes que declarar _
dentro o fuera de la expresión y solo tienes que escribir
int.TryParse(s, out _);
Trata de hacer este liner pre C # 7:
private void btnDialogOk_Click_1(object sender, RoutedEventArgs e)
{
DialogResult = int.TryParse(Answer, out _);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-21 07:39:49