c# - functions - ¿Por qué este resultado condicional(nulo ||! TryParse) en "uso de variable local no asignada"?
static dynamic c# (3)
El siguiente código da como resultado el uso de la variable local no asignada "numberOfGroups" :
int numberOfGroups;
if(options.NumberOfGroups == null || !int.TryParse(options.NumberOfGroups, out numberOfGroups))
{
numberOfGroups = 10;
}
Sin embargo, este código funciona bien (aunque, ReSharper dice que = 10
es redundante):
int numberOfGroups = 10;
if(options.NumberOfGroups == null || !int.TryParse(options.NumberOfGroups, out numberOfGroups))
{
numberOfGroups = 10;
}
Me estoy perdiendo algo, o al compilador no le gusta mi ||
?
He reducido esto a dynamic
causando los problemas (las options
eran una variable dinámica en mi código anterior). La pregunta aún permanece, ¿por qué no puedo hacer esto ?
Este código no se compila:
internal class Program
{
#region Static Methods
private static void Main(string[] args)
{
dynamic myString = args[0];
int myInt;
if(myString == null || !int.TryParse(myString, out myInt))
{
myInt = 10;
}
Console.WriteLine(myInt);
}
#endregion
}
Sin embargo, este código hace :
internal class Program
{
#region Static Methods
private static void Main(string[] args)
{
var myString = args[0]; // var would be string
int myInt;
if(myString == null || !int.TryParse(myString, out myInt))
{
myInt = 10;
}
Console.WriteLine(myInt);
}
#endregion
}
No me di cuenta de que la dynamic
sería un factor en esto.
Es posible que la variable no esté asignada si el valor de la expresión dinámica es de un tipo con un operador true
sobrecargado .
El ||
el operador invocará al operador true
para decidir si evalúa el lado derecho, y luego el enunciado if
invocará al operador true
para decidir si evalúa su cuerpo. Para un bool
normal, estos siempre devolverán el mismo resultado, por lo que se evaluará exactamente uno, pero para un operador definido por el usuario ¡no existe tal garantía!
Partiendo de la reproducción de Eric Lippert, aquí hay un programa corto y completo que demuestra un caso en el que ninguna ruta se ejecutaría y la variable tendría su valor inicial:
using System;
class Program
{
static bool M(out int x)
{
x = 123;
return true;
}
static int N(dynamic d)
{
int y = 3;
if (d || M(out y))
y = 10;
return y;
}
static void Main(string[] args)
{
var result = N(new EvilBool());
// Prints 3!
Console.WriteLine(result);
}
}
class EvilBool
{
private bool value;
public static bool operator true(EvilBool b)
{
// Return true the first time this is called
// and false the second time
b.value = !b.value;
return b.value;
}
public static bool operator false(EvilBool b)
{
throw new NotImplementedException();
}
}
Estoy bastante seguro de que esto es un error del compilador. Buen hallazgo!
Editar: no es un error, como lo demuestra Quartermeister; dynamic podría implementar un operador true
extraño que podría causar que y
nunca se inicialice.
Aquí hay una reproducción mínima:
class Program
{
static bool M(out int x)
{
x = 123;
return true;
}
static int N(dynamic d)
{
int y;
if(d || M(out y))
y = 10;
return y;
}
}
No veo ninguna razón por la que eso debería ser ilegal; si reemplazas dynamic con bool compila muy bien.
De hecho, me reuniré con el equipo de C # mañana; Lo mencionaré a ellos. Disculpas por el error!
De MSDN (énfasis mío):
El tipo dinámico permite que las operaciones en las que ocurre omitan la verificación de tipos en tiempo de compilación . En cambio, estas operaciones se resuelven en tiempo de ejecución . El tipo dinámico simplifica el acceso a las API COM, como las API de automatización de Office, y también a las API dinámicas, como las bibliotecas de IronPython, y al Modelo de objetos de documento HTML (DOM).
Tipo dinámico se comporta como tipo de objeto en la mayoría de las circunstancias. Sin embargo, las operaciones que contienen expresiones de tipo dinámico no se resuelven o el tipo comprueba el compilador.
Como el compilador no escribe check o resuelve ninguna operación que contenga expresiones de tipo dinámico, no puede garantizar que la variable se asigne mediante el uso de TryParse()
.