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 = 10es redundante):
int numberOfGroups = 10;
if(options.NumberOfGroups == null || !int.TryParse(options.NumberOfGroups, out numberOfGroups))
{
    numberOfGroups = 10;
}
¿Me falta algo o al compilador no le gusta mi ||?
He reducido esto para dynamiccausar los problemas ( optionsera una variable dinámica en mi código anterior). La pregunta sigue siendo, ¿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 sí :
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 dynamicque sería un factor en esto.

outparámetro como entradaoutparámetro. Ciertamente es interesante considerar qué código auxiliar debería producir el compilador para evitar el problema, o si eso es posible.Respuestas:
Estoy bastante seguro de que se trata de un error del compilador. ¡Buen hallazgo!
Editar: no es un error, como demuestra Quartermeister; dynamic podría implementar un
trueoperador extraño que podría causaryque nunca se inicialice.Aquí hay una reproducción mínima:
No veo ninguna razón por la que eso deba ser ilegal; si reemplaza dynamic con bool, se compila bien.
De hecho, mañana me reuniré con el equipo de C #; Se lo mencionaré. ¡Disculpas por el error!
fuente
dpuede ser de un tipo con untrueoperador sobrecargado . Publiqué una respuesta con un ejemplo en el que no se toma ninguna rama.Es posible que la variable no esté asignada si el valor de la expresión dinámica es de un tipo con un operador sobrecargado
true.El
||operador invocará altrueoperador para decidir si evaluar el lado derecho, y luego laifdeclaración invocará altrueoperador para decidir si evaluar su cuerpo. Para una normalbool, estos siempre devolverán el mismo resultado y, por lo tanto, 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:
fuente
devaluarse dos veces? (No estoy discutiendo que claramente lo sea , como ha mostrado). Hubiera esperado que el resultado evaluado detrue(desde la primera invocación del operador, causa por||) se "pasara" a laifdeclaración. Eso es ciertamente lo que sucedería si pones una llamada de función allí, por ejemplo.dse evalúa solo una vez, como es de esperar. Es eltrueoperador el que se invoca dos veces, una por||una y otra porif.var cond = d || M(out y); if (cond) { ... }. Primero evaluamosdpara obtener unaEvilBoolreferencia de objeto. Para evaluar el||, primero invocamosEvilBool.truecon esa referencia. Eso devuelve verdadero, por lo que cortocircuitamos y no invocamosM, y luego asignamos la referencia acond. Luego, pasamos a laifdeclaración. Laifdeclaración evalúa su condición llamandoEvilBool.true.De MSDN (el énfasis es mío):
Dado que el compilador no comprueba el tipo ni resuelve ninguna operación que contenga expresiones de tipo dinámico, no puede asegurar que la variable se asignará mediante el uso de
TryParse().fuente
numberGroupsse asigna (en elif truebloque), si no, la segunda condición garantiza la asignación (víaout).myString == null(confiando solo enTryParse).ifexpresión completa ) involucra unadynamicvariable, no se resuelve en el momento de la compilación (el compilador, por lo tanto, no puede hacer esas suposiciones).