247

Does C# 4.0 allow optional out or ref arguments?

shA.t
  • 16,580
  • 5
  • 54
  • 111
Joe Daley
  • 45,356
  • 15
  • 65
  • 64
  • 2
    Weell, 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. – Andy Dent May 20 '10 at 02:13
  • 62
    @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. – Roman Starkov Sep 15 '10 at 17:07
  • 6
    Maybe 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. – Adam Tolley Dec 17 '10 at 19:08
  • 9
    C# doesn't, but VB.NET does. – Jason Dec 21 '10 at 21:13
  • 6
    This 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 for `null` to proceed with populating the argument (*for those familiar, think `preg_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. – Dan Lugg Feb 05 '12 at 05:53
  • Just 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. – Tony Aug 25 '14 at 15:54
  • https://devblogs.microsoft.com/dotnet/whats-new-in-csharp-7-0/#user-content-out-variables was saying "We plan to allow “wildcards” as out parameters as well, in the form of a *, to let you ignore out parameters you don’t care about: p.GetCoordinates(out int x, out *); // I only care about x --- Note: It is still uncertain whether wildcards make it into C# 7.0 - However at https://devblogs.microsoft.com/dotnet/new-features-in-c-7-0/ I don't see mention of wildcards, so probably they didn't keep that feature – George Birbilis May 02 '23 at 08:14

11 Answers11

259

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.)

Neuron
  • 5,141
  • 5
  • 38
  • 59
Dunc
  • 18,404
  • 6
  • 86
  • 103
  • 8
    any idea for more elegant solution than declaring temp/dummy? – Louis Rhys Jul 17 '12 at 03:15
  • 23
    What's not elegant about that? Looks perfectly decent to me. – Neutrino Dec 18 '13 at 16:08
  • 32
    Maybe 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. – o0'. Jul 07 '14 at 21:46
  • 9
    Hold on @o0'. In C# 7.0 you will be able to do this: `return SomeMethod(out string temp)`. See more here: https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/#user-content-out-variables – Oskar Oct 07 '16 at 07:55
  • 9
    In C# 7.0 you can use a temporary write-only variable like: `return SomeMethod(out _);` – Reiner Oct 13 '17 at 08:26
  • If you have multiple optional out parameters, you still end up with a cartesian product set of overloads. – Brain2000 May 09 '19 at 17:28
  • @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? – Dunc May 10 '19 at 08:42
  • @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. – Brain2000 May 10 '19 at 23:16
99

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 or out parameter cannot have a default-argument.
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • Alternatively, 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 – Chad Dec 20 '19 at 17:12
  • Not if you have 10 optional ref parameters. Then you have a giant mess when trying to port to C# – Brain2000 Mar 18 '22 at 15:14
71

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);
}
Robin R
  • 1,037
  • 10
  • 6
  • 20
    It'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. – Ken Smith May 05 '14 at 17:39
  • 2
    I like it, but if you don't want to create a new class, you can simulate it by passing in a single element array. – zumalifeguard Feb 06 '15 at 21:13
  • Can someone please elaborate on this: "the compiler won't enforce the requirement that the out parameter be assigned before exiting the method"? – JohnC Nov 17 '20 at 03:59
  • I 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. – Robin R Nov 18 '20 at 00:12
  • 1
    If the compiler complained then it would not be optional. – Paul Childs Mar 10 '21 at 01:18
  • I 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! – Matt Jan 20 '22 at 12:15
34

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.

neonblitzer
  • 124
  • 1
  • 2
  • 10
wizard07KSU
  • 754
  • 6
  • 14
8

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.

jbdeguzman
  • 926
  • 7
  • 11
5

No, but you can use a delegate (e.g. Action) as an alternative.

Inspired in part by Robin R's answer when facing a situation where I thought I wanted an optional out parameter, I instead used an Action delegate. I've borrowed his example code to modify for use of Action<int> in order to show the differences and similarities:

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);
}

This has the advantage that the optional variable appears in the source as a normal int (the compiler wraps it in a closure class, rather than us wrapping it explicitly in a user-defined class).

The variable needs explicit initialisation because the compiler cannot assume that the Action will be called before the function call exits.

It's not suitable for all use cases, but worked well for my real use case (a function that provides data for a unit test, and where a new unit test needed access to some internal state not present in the return value).

Steve
  • 613
  • 5
  • 15
0

Use an overloaded method without the out parameter to call the one with the out parameter for C# 6.0 and lower. I'm not sure why a C# 7.0 for .NET Core is even the correct answer for this thread when it was specifically asked if C# 4.0 can have an optional out parameter. The answer is NO!

Mr_CSharp
  • 69
  • 1
0

For simple types you can do this using unsafe code, though it's not idiomatic nor recommended. Like so:

// unsafe since remainder can point anywhere
// and we can do arbitrary pointer manipulation
public unsafe int Divide( int x, int y, int* remainder = null ) {
    if( null != remainder ) *remainder = x % y;
    return x / y;
}

That said, there's no theoretical reason C# couldn't eventually allow something like the above with safe code, such as this below:

// safe because remainder must point to a valid int or to nothing
// and we cannot do arbitrary pointer manipulation
public int Divide( int x, int y, out? int remainder = null ) {
    if( null != remainder ) *remainder = x % y;
    return x / y;
}

Things could get interesting though:

// remainder is an optional output parameter
// (to a nullable reference type)
public int Divide( int x, int y, out? object? remainder = null ) {
    if( null != remainder ) *remainder = 0 != y ? x % y : null;
    return x / y;
}
0

The direct question has been answered in other well-upvoted answers, but sometimes it pays to consider other approaches based on what you're trying to achieve.

If you're wanting an optional parameter to allow the caller to possibly request extra data from your method on which to base some decision, an alternative design is to move that decision logic into your method and allow the caller to optionally pass a value for that decision criteria in. For example, here is a method which determines the compass point of a vector, in which we might want to pass back the magnitude of the vector so that the caller can potentially decide if some minimum threshold should be reached before the compass-point judgement is far enough away from the origin and therefore unequivocally valid:

public enum Quadrant {
    North,
    East,
    South,
    West
}

// INVALID CODE WITH MADE-UP USAGE PATTERN OF "OPTIONAL" OUT PARAMETER
public Quadrant GetJoystickQuadrant([optional] out magnitude)
{
    Vector2 pos = GetJoystickPositionXY();
    float azimuth = Mathf.Atan2(pos.y, pos.x) * 180.0f / Mathf.PI;
    Quadrant q;
    if (azimuth > -45.0f && azimuth <= 45.0f) q = Quadrant.East;
    else if (azimuth > 45.0f && azimuth <= 135.0f) q = Quadrant.North;
    else if (azimuth > -135.0f && azimuth <= -45.0f) q = Quadrant.South;
    else q = Quadrant.West;
    if ([optonal.isPresent(magnitude)]) magnitude = pos.Length();
    return q;
}

In this case we could move that "minimum magnitude" logic into the method and end-up with a much cleaner implementation, especially because calculating the magnitude involves a square-root so is computationally inefficient if all we want to do is a comparison of magnitudes, since we can do that with squared values:

public enum Quadrant {
    None, // Too close to origin to judge.
    North,
    East,
    South,
    West
}

public Quadrant GetJoystickQuadrant(float minimumMagnitude = 0.33f)
{
    Vector2 pos = GetJoystickPosition();
    if (minimumMagnitude > 0.0f && pos.LengthSquared() < minimumMagnitude * minimumMagnitude)
    {
        return Quadrant.None;
    }
    float azimuth = Mathf.Atan2(pos.y, pos.x) * 180.0f / Mathf.PI;
    if (azimuth > -45.0f && azimuth <= 45.0f) return Quadrant.East;
    else if (azimuth > 45.0f && azimuth <= 135.0f) return Quadrant.North;
    else if (azimuth > -135.0f && azimuth <= -45.0f) return Quadrant.South;
    return Quadrant.West;
}

Of course, that might not always be viable. Since other answers mention C# 7.0, if instead what you're really doing is returning two values and allowing the caller to optionally ignore one, idiomatic C# would be to return a tuple of the two values, and use C# 7.0's Tuples with positional initializers and the _ "discard" parameter:

public (Quadrant, float) GetJoystickQuadrantAndMagnitude()
{
    Vector2 pos = GetJoystickPositionXY();
    float azimuth = Mathf.Atan2(pos.y, pos.x) * 180.0f / Mathf.PI;
    Quadrant q;
    if (azimuth > -45.0f && azimuth <= 45.0f) q = Quadrant.East;
    else if (azimuth > 45.0f && azimuth <= 135.0f) q = Quadrant.North;
    else if (azimuth > -135.0f && azimuth <= -45.0f) q = Quadrant.South;
    else q = Quadrant.West;
    return (q, pos.Length());
}

(Quadrant q, _) = GetJoystickQuadrantAndMagnitude();
if (q == Quadrant.South)
{
    // Do something.
}
bleater
  • 5,098
  • 50
  • 48
-2

What about like this?

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

You still have to pass a value to the parameter from C# but it is an optional ref param.

Aaron L.
  • 225
  • 1
  • 12
-4
void foo(ref int? n)
{
    return null;
}
  • 4
    Please add some explanation on your code to make everyone understand the concept easily – techspider Jun 15 '16 at 13:54
  • 2
    Although 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. – Toby Speight Jun 15 '16 at 20:49
  • 4
    This will result in a syntax error as method has void return type. Also, does not answer question. – Nathan Montez Jan 12 '17 at 21:11