C# 4.0 optional out/ref arguments
Solution 1
As already mentioned, this is simply not allowed and I think it makes a very good sense. However, to add some more details, here is a quote from the C# 4.0 Specification, section 21.1:
Formal parameters of constructors, methods, indexers and delegate types can be declared optional:
fixed-parameter:
attributesopt parameter-modifieropt type identifier default-argumentopt
default-argument:
= expression
- A fixed-parameter with a default-argument is an optional parameter, whereas a fixed-parameter without a default-argument is a required parameter.
- A required parameter cannot appear after an optional parameter in a formal-parameter-list.
- A
ref
orout
parameter cannot have a default-argument.
Solution 2
No.
A workaround is to overload with another method that doesn't have out / ref parameters, and which just calls your current method.
public bool SomeMethod(out string input)
{
...
}
// new overload
public bool SomeMethod()
{
string temp;
return SomeMethod(out temp);
}
If you have C# 7.0, you can simplify:
// new overload
public bool SomeMethod()
{
return SomeMethod(out _); // declare out as an inline discard variable
}
(Thanks @Oskar / @Reiner for pointing this out.)
Solution 3
No, but another great alternative is having the method use a generic template class for optional parameters as follows:
public class OptionalOut<Type>
{
public Type Result { get; set; }
}
Then you can use it as follows:
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);
}
Solution 4
There actually is a way to do this that is allowed by C#. This gets back to C++, and rather violates the nice Object-Oriented structure of C#.
USE THIS METHOD WITH CAUTION!
Here's the way you declare and write your function with an optional parameter:
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.
}
}
Then call the function like this:
unsafe { OptionalOutParameter(); } // does nothing
int MyInteger = 0;
unsafe { OptionalOutParameter(&MyInteger); } // pass in the address of MyInteger.
In order to get this to compile, you will need to enable unsafe code in the project options. This is a really hacky solution that usually shouldn't be used, but if you for some strange, arcane, mysterious, management-inspired decision, REALLY need an optional out parameter in C#, then this will allow you to do just that.
Solution 5
ICYMI: Included on the new features for C# 7.0 enumerated here, "discards" is now allowed as out parameters in the form of a _, to let you ignore out parameters you don’t care about:
p.GetCoordinates(out var x, out _); // I only care about x
P.S. if you're also confused with the part "out var x", read the new feature about "Out Variables" on the link as well.
Related videos on Youtube
user3156301
Updated on April 22, 2022Comments
-
user3156301 about 2 years
Does C# 4.0 allow optional
out
orref
arguments?-
Andy Dent about 14 yearsWeell, C++ effectively has them for "out" parameters - you can have an address argument initialised to null and it's quite common to write library code that will only populate such a return structure if the pointer is non-null. That's an idiom going back to using null for "optional arguments" in C APIs.
-
Roman Starkov almost 14 years@Ed and everyone: why would this make no sense? If a function "returns" a value via "out", I don't want to be forced to accept it. Now I know that for technical reasons the compiler still has to pass something in, but there's no reason why it couldn't just create a dummy local for me behind my back.
-
Adam Tolley over 13 yearsMaybe it makes no sense from the standpoint of how things are implemented or what an optional parameter actually is. But like romkyns said, it would be really nice to have "optional out arguments" - parse that in English rather than CLR and it becomes reasonable and in IMO desirable.
-
Ricardo Gomes over 13 yearsC# doesn't, but VB.NET does.
-
Dan Lugg over 12 yearsThis has been beaten to death, however, I can't help but mention my support for optional out arguments. I've become fairly accustomed to optional arguments by reference via setting a
null
default (I come from PHP) and testing fornull
to proceed with populating the argument (for those familiar, thinkpreg_match()
) Anyway, while I understand from a technical point this may currently be impossible, and that PHP and C# are rather incomparable, it would still be a "nice" tool to have available. -
Tony almost 10 yearsJust use an overloaded method that does not take the out parameter in question, if you have a few of them you want optional though this could get messy.
-
-
Louis Rhys almost 12 yearsany idea for more elegant solution than declaring temp/dummy?
-
Neutrino over 10 yearsWhat's not elegant about that? Looks perfectly decent to me.
-
Ken Smith about 10 yearsIt's a very reasonable solution, but one thing to be aware of is that the compiler won't enforce the requirement that the out parameter be assigned before exiting the method.
-
o0'. almost 10 yearsMaybe decent, but elegant is definitely on another league. The fact there's no better solution doesn't mean this is state-of-the-art by decree.
-
zumalifeguard over 9 yearsI like it, but if you don't want to create a new class, you can simulate it by passing in a single element array.
-
Arturo Torres Sánchez over 9 years“You still have to pass a value to the parameter from C#”... This makes it not optional.
-
techspider about 8 yearsPlease add some explanation on your code to make everyone understand the concept easily
-
Toby Speight about 8 yearsAlthough this code may answer the question, providing additional context regarding why and/or how it answers the question would significantly improve its long-term value. Please edit your answer to add some explanation.
-
Oskar over 7 yearsHold on @o0'. In C# 7.0 you will be able to do this:
return SomeMethod(out string temp)
. See more here: blogs.msdn.microsoft.com/dotnet/2016/08/24/… -
Nathan Montez over 7 yearsThis will result in a syntax error as method has void return type. Also, does not answer question.
-
ToolmakerSteve about 7 yearsC# ignores the
[Optional]
annotation. This does not help. -
Reiner over 6 yearsIn C# 7.0 you can use a temporary write-only variable like:
return SomeMethod(out _);
-
Onur Topal over 5 yearsis it _ or * "p.GetCoordinates(out int x, out *); // I only care about x"
-
Onur Topal over 5 yearslooks like I was looking an older version of the document.
-
Brain2000 about 5 yearsIf you have multiple optional out parameters, you still end up with a cartesian product set of overloads.
-
Dunc about 5 years@Brain2000 True - I'd maybe consider an alternative approach if you need multiple optional outs, or as you say you'd end up with a potentially confusing list of overloads, plus you can't have two overloads with the same signature. Maybe introduce a parameter object or return a response object?
-
Brain2000 about 5 years@Dunc With complex HR software, when creating certain events, we have to optionally return one or more states depending on where the function is called from. I think our most complex one has about 10 optional refs. Most of the time they aren't used, or we could look up the data after the fact, but that would be extra calls to the database. We also have C# modules that call the foundation code in VB.net. When that happens, the C# code ends up looking like a disaster took place with all the unused temp variables.
-
Chad over 4 yearsAlternatively, you can create an overload with a ref/out parameter. Yes, you'll have two function definitions, but it will accomplish what you're after
-
JohnC over 3 yearsCan someone please elaborate on this: "the compiler won't enforce the requirement that the out parameter be assigned before exiting the method"?
-
Robin R over 3 yearsI assume they meant that if
outResult
was not set to any value the the compiler would not complain. In other words, it might be easy to forget to set an out variable accidentally. -
Paul Childs over 3 yearsIf the compiler complained then it would not be optional.
-
Paul Childs over 3 yearsDiscards aren't really optional variables. It is only for a bit of syntactic sugar at the calling code level. The function itself has no knowledge it has been called with a discard.
-
Matt over 2 yearsI like this approach more than having to use discards like in this example:
var canParse = int.TryParse("123", out _);
. Your approach is truly optional. Great! -
Brain2000 over 2 yearsNot if you have 10 optional ref parameters. Then you have a giant mess when trying to port to C#
-
Brain2000 over 2 yearsWhy can't the discard be automatic like it is in VB.net?