C # 4.0 argumentos opcionales out/ref


¿Permite C# 4.0 argumentos opcionales out o ref?

Author: shA.t, 2010-05-20

8 answers

Como ya se mencionó, esto simplemente no está permitido y creo que tiene un muy buen sentido. Sin embargo, para agregar algunos detalles más, aquí hay una cita de la Especificación C# 4.0 , sección 21.1:

Los parámetros formales de constructores, métodos, indexadores y tipos de delegados pueden declararse opcionales:

Parámetro fijo:
    atributosopt parámetro-modificador opt identificador de tipo por defecto-argumento opt
default-argumento:
    expresión =

  • Un fija el parámetro con a default-argumento es parámetro opcional, mientras que un fija el parámetro sin a default-argumento es a parámetro requerido.
  • Un parámetro requerido no puede aparecer después de un parámetro opcional en una formal-parameter-list.
  • A ref o out el parámetro no puede tener default-argumento.
 85
Author: Tomas Petricek,
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
2010-05-20 02:06:58

No.

Una solución es sobrecargar con otro método que no tiene parámetros out / ref, y que solo llama a su método actual.

public bool SomeMethod(out string input)
{
    ...
}

// new overload
public bool SomeMethod()
{
    string temp;
    return SomeMethod(out temp);
}

Actualización: Si tiene C # 7.0 , puede simplificar:

// new overload
public bool SomeMethod()
{
    return SomeMethod(out _);    // declare out as an inline discard variable
}

(Gracias @Oskar / @Reiner por señalar esto.)

 153
Author: Dunc,
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-01-23 09:59:10

No, pero otra gran alternativa es hacer que el método use una clase de plantilla genérica para parámetros opcionales de la siguiente manera:

public class OptionalOut<Type>
{
    public Type Result { get; set; }
}

Entonces puedes usarlo de la siguiente manera:

public string foo(string value, OptionalOut<int> outResult = null)
{
    // .. do something

    if (outResult != null) {
        outResult.Result = 100;
    }

    return value;
}

public void bar ()
{
    string str = "bar";

    string result;
    OptionalOut<int> optional = new OptionalOut<int> ();

    // example: call without the optional out parameter
    result = foo (str);
    Console.WriteLine ("Output was {0} with no optional value used", result);

    // example: call it with optional parameter
    result = foo (str, optional);
    Console.WriteLine ("Output was {0} with optional value of {1}", result, optional.Result);

    // example: call it with named optional parameter
    foo (str, outResult: optional);
    Console.WriteLine ("Output was {0} with optional value of {1}", result, optional.Result);
}
 60
Author: Robin R,
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
2014-02-24 15:06:06

En realidad hay una forma de hacer esto que está permitida por C#. Esto vuelve a C++, y más bien viola la bonita estructura Orientada a Objetos de C#.

UTILICE ESTE MÉTODO CON PRECAUCIÓN!

Esta es la forma en que declara y escribe su función con un parámetro opcional:

unsafe public void OptionalOutParameter(int* pOutParam = null)
{
    int lInteger = 5;
    // If the parameter is NULL, the caller doesn't care about this value.
    if (pOutParam != null) 
    { 
        // If it isn't null, the caller has provided the address of an integer.
        *pOutParam = lInteger; // Dereference the pointer and assign the return value.
    }
}

Luego llame a la función de esta manera:

unsafe { OptionalOutParameter(); } // does nothing
int MyInteger = 0;
unsafe { OptionalOutParameter(&MyInteger); } // pass in the address of MyInteger.

Para que esto se compile, necesitará habilitar el código inseguro en las opciones del proyecto. Esta es una solución realmente hacky que por lo general no debería ser utilizado, pero si por alguna extraña, arcana, misteriosa, decisión inspirada en la gestión, REALMENTE necesita un parámetro de salida opcional en C#, entonces esto le permitirá hacer precisamente eso.

 24
Author: wizard07KSU,
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
2015-08-10 18:31:01

ICYMI: Incluido en las nuevas características para C# 7.0 enumerado aquí , "descartes" ahora se permite como parámetros de salida en forma de un_, para que pueda ignorar los parámetros que no le importan:

p.GetCoordinates(out var x, out _); // I only care about x

P.D. si también está confundido con la parte "out var x", lea la nueva característica sobre "Out Variables" en el enlace también.

 5
Author: jbdeguzman,
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-10 08:08:24

No, pero puede usar un delegado (por ejemplo, Action) como alternativa.

Inspirado en parte por la respuesta de Robin R cuando me enfrenté a una situación en la que pensé que quería un parámetro de salida opcional, en su lugar usé un delegado Action. He tomado prestado su código de ejemplo para modificar el uso de Action<int> con el fin de mostrar las diferencias y similitudes:

public string foo(string value, Action<int> outResult = null)
{
    // .. do something

    outResult?.Invoke(100);

    return value;
}

public void bar ()
{
    string str = "bar";

    string result;
    int optional = 0;

    // example: call without the optional out parameter
    result = foo (str);
    Console.WriteLine ("Output was {0} with no optional value used", result);

    // example: call it with optional parameter
    result = foo (str, x => optional = x);
    Console.WriteLine ("Output was {0} with optional value of {1}", result, optional);

    // example: call it with named optional parameter
    foo (str, outResult: x => optional = x);
    Console.WriteLine ("Output was {0} with optional value of {1}", result, optional);
}

Esto tiene la ventaja de que la variable opcional aparece en la fuente como una int normal (el compilador la envuelve en una clase closure, en lugar de envolverlo explícitamente en una clase definida por el usuario).

La variable necesita inicialización explícita porque el compilador no puede asumir que se llamará a Action antes de que salga la llamada a la función.

No es adecuado para todos los casos de uso, pero funcionó bien para mi caso de uso real (una función que proporciona datos para una prueba unitaria, y donde una nueva prueba unitaria necesitaba acceso a algún estado interno no presente en el valor devuelto).

 0
Author: Steve,
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-11-17 09:33:43

¿Qué tal así?

public bool OptionalOutParamMethod([Optional] ref string pOutParam)
{
    return true;
}

Todavía tiene que pasar un valor al parámetro desde C#, pero es un parámetro de referencia opcional.

 -2
Author: Aaron L.,
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
2014-10-24 21:47:44
void foo(ref int? n)
{
    return null;
}
 -4
Author: user6469927,
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
2016-06-15 13:47:26