Colocación del análisis de parámetros de salida del procedimiento almacenado

Encontré este error debido a un análisis aparentemente fuera de lugar de un parámetro de procedimiento almacenado de salida.

El parámetro de salida 'cuálID' debe asignarse antes de que el control abandone el método actual

Código:

public static bool CreateFilmTest(string param1, string param2, out int whichID)
{
            DbCommand com = GenericDataAccess.CreateCommand();
            com.CommandText = "CatalogCreateFilmTest";

            DbParameter param = com.CreateParameter();
            param.ParameterName = "@param1";
            param.Value = param1;
            param.DbType = DbType.String;
            param.Size = 200;
            com.Parameters.Add(param);
            ..........            
            param = com.CreateParameter();
            param.ParameterName = "@Fid";
            param.Direction = ParameterDirection.Output;
            param.DbType = DbType.Int32;
            com.Parameters.Add(param);

            int result = -1;

            try
            {
                result = GenericDataAccess.ExecuteNonQuery(com);

                whichID = Int32.Parse(com.Parameters["@Fid"].Value.ToString());

            }
            catch
            {
                // ....
            }


           return (result >= 1);
}

Si coloco el: whichID = Int32.Parse(com.Parameters["@Fid"].Value.ToString()); línea inmediatamente antes de la línea de retorno, el método se ejecuta correctamente y da el resultado correcto.

Sin embargo, si lo coloco entre paréntesis de prueba, da el error mencionado al principio.

¿Porque?

Mi primera opción fue ponerlo dentro del soporte de prueba, porque SI por alguna razón el ExecuteNonQuery falla, no tiene sentido manejar su parámetro de salida (whichID). Por lo tanto, vi mejor acoplar los dos elementos (ejecución del procedimiento y manejo del parámetro de salida del procedimiento) dentro del bloque de prueba, que activa en caso de error el manejo elegante de tal situación dentro catch.

Su entrada es muy apreciada. Gracias. ana

preguntado el 12 de junio de 12 a las 12:06

Si colocas tu whichID =.... línea dentro de try..catch - deberá inicializar el whichID salir parámetro con un valor en algún lugar fuera del try...catch bloque (o dentro del catch parte). El salir parámetro debe siempre se le asigna un valor -

3 Respuestas

El razonamiento es que no hay una asignación razonablemente cierta si la coloca dentro del intento. Puede evitar esto asignándole un valor predeterminado anteriormente en el método (por ejemplo, configurándolo en cero en la primera línea).

Respondido el 12 de junio de 12 a las 12:06

Si la memoria no me falla es porque el try está compilado de tal manera que incluye un interior try, lo que significa que el flujo del programa podría no entrar correctamente en el try antes de seguir adelante (aunque por lo general asumes que try no interrumpe el flujo del programa de la misma manera que, digamos, if hace).

Esto activaría la verificación del compilador contra out parámetros asignados antes de salir del método.

Simplemente predetermina el valor en la parte superior del método.


La memoria sirve... la especificación del lenguaje lo sabe todo.

12.3.3.15 Declaraciones try-catch-finalmente (específicamente análisis de asignación para try-catch-finally).

Análisis de asignación definitiva para una instrucción try-catch-finally de la forma:

try [try-block]
catch ( … ) [catch-block-1]
…
catch ( … ) [catch-block-n]
finally [finally-block]

se hace como si la sentencia fuera una sentencia try-finally que incluye una sentencia try-catch:

try {
try [try-block]
catch ( … ) [catch-block-1]
…
catch ( … ) [catch-block-n]
}
finally [finally-block]

Un ejemplo:

class A
{
    static void F() {
        int i, j;
        try {
            goto LABEL;
            // neither i nor j definitely assigned
            i = 1;
            // i definitely assigned
        }
        catch {
            // neither i nor j definitely assigned
            i = 3;
            // i definitely assigned
        }
        finally {
            // neither i nor j definitely assigned
            j = 5;
            // j definitely assigned
        }
        // i and j definitely assigned
        LABEL:;
        // j definitely assigned
    }
}

Respondido el 12 de junio de 12 a las 13:06

La razón por la que obtiene ese error se debe a la forma en que el compilador maneja try/catch. Un bloque try/catch es una declaración condicional en cierto sentido. El código que contiene solo se ejecuta si el código anterior no genera una excepción, y el código en sí solo termina de ejecutarse si no genera una excepción.

Si solo está definiendo una variable dentro del intento (o solo dentro de las capturas), entonces no puede estar seguro de que esas líneas de código se ejecutarán. Si su variable solo está definida dentro del bloque de prueba, entonces posiblemente podría omitirse si hay una excepción antes, o en la línea que hace la definición. Si su variable solo está definida en la cláusula catch, se omitirá si no se producen excepciones.

Es mejor que declare un valor predeterminado antes de ingresar al bloque try-catch, o que declare un valor de falla dentro de su cláusula catch.

Respondido el 12 de junio de 12 a las 13:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.