¿C # 4.0 permite opcionales out
o ref
argumentos?
fuente
¿C # 4.0 permite opcionales out
o ref
argumentos?
Como ya se mencionó, esto simplemente no está permitido y creo que tiene mucho sentido. Sin embargo, para agregar más detalles, 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:
atributos opt parámetro-modificador opt tipo identificador argumento -predeterminado opt
argumento-predeterminado:
= expresión
- Un parámetro fijo con un argumento predeterminado es un parámetro opcional , mientras que un parámetro fijo sin un argumento predeterminado es un parámetro obligatorio .
- Un parámetro requerido no puede aparecer después de un parámetro opcional en una lista de parámetros formales .
- Un parámetro
ref
oout
no puede tener un argumento predeterminado .
No.
Una solución alternativa es sobrecargar con otro método que no tiene parámetros out / ref, y que simplemente 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).
return SomeMethod(out string temp)
. Ver más aquí: blogs.msdn.microsoft.com/dotnet/2016/08/24/…
return SomeMethod(out _);
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 puede 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);
}
En realidad, hay una manera de hacer esto que C # permite. Esto vuelve a C ++, y más bien viola la agradable estructura orientada a objetos de C #.
¡USE 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, deberá habilitar el código inseguro en las opciones del proyecto. Esta es una solución realmente hacky que generalmente no debería usarse, pero si por alguna decisión extraña, arcana, misteriosa e inspirada en la administración, REALMENTE necesita un parámetro de salida opcional en C #, entonces esto le permitirá hacer exactamente eso.
ICYMI: incluidas en las nuevas funciones para C # 7.0 enumeradas aquí , "descartes" ahora está permitido como parámetros externos en forma de _, para permitirle ignorar los parámetros que no le interesan:
p.GetCoordinates(out var x, out _); // I only care about x
PD: si también estás confundido con la parte "out var x", lee también la nueva función sobre "Out Variables" en el enlace.
No, pero puede usar un delegado (por ejemplo Action
) como alternativa.
Inspirado en parte por la respuesta de Robin R al enfrentar una situación en la que pensé que quería un parámetro de salida opcional, en su lugar utilicé un Action
delegado. He tomado prestado su código de ejemplo para modificarlo para usarlo Action<int>
a 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 un int normal (el compilador la envuelve en una clase de cierre, en lugar de que la envuelvamos explícitamente en una clase definida por el usuario).
La variable necesita una inicialización explícita porque el compilador no puede suponer que Action
se invocará antes de que finalice 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 de retorno).
Use un método sobrecargado sin el parámetro out para llamar al que tiene el parámetro out para C # 6.0 y versiones inferiores. No estoy seguro de por qué un C # 7.0 para .NET Core es incluso la respuesta correcta para este hilo cuando se le preguntó específicamente si C # 4.0 puede tener un parámetro de salida opcional. ¡La respuesta es no!
¿Qué tal así?
public bool OptionalOutParamMethod([Optional] ref string pOutParam)
{
return true;
}
Aún debe pasar un valor al parámetro desde C #, pero es un parámetro de referencia opcional.
[Optional]
anotación. Esto no ayuda
void foo(ref int? n)
{
return null;
}
null
valor predeterminado ( vengo de PHP ) y probando paranull
proceder a completar el argumento ( para aquellos familiares, piensenpreg_match()
) De todos modos, aunque entiendo desde un punto técnico esto puede ser actualmente imposible, y que PHP y C # son bastante incomparables, todavía sería una herramienta " agradable " tener disponible.