C# 4.0 optional out/ref arguments

C# 4.0Optional ParametersOptional Arguments

C# 4.0 Problem Overview


Does C# 4.0 allow optional out or ref arguments?

C# 4.0 Solutions


Solution 1 - C# 4.0

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 2 - C# 4.0

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.

Solution 3 - C# 4.0

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 - C# 4.0

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 - C# 4.0

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.

Solution 6 - C# 4.0

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

Solution 7 - C# 4.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!

Solution 8 - C# 4.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;
}

Solution 9 - C# 4.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.
}

Solution 10 - C# 4.0

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.

Solution 11 - C# 4.0

void foo(ref int? n)
{
    return null;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJoe DaleyView Question on Stackoverflow
Solution 1 - C# 4.0DuncView Answer on Stackoverflow
Solution 2 - C# 4.0Tomas PetricekView Answer on Stackoverflow
Solution 3 - C# 4.0Robin RView Answer on Stackoverflow
Solution 4 - C# 4.0wizard07KSUView Answer on Stackoverflow
Solution 5 - C# 4.0jbdeguzmanView Answer on Stackoverflow
Solution 6 - C# 4.0SteveView Answer on Stackoverflow
Solution 7 - C# 4.0Mr_CSharpView Answer on Stackoverflow
Solution 8 - C# 4.0Elliott PrechterView Answer on Stackoverflow
Solution 9 - C# 4.0bleaterView Answer on Stackoverflow
Solution 10 - C# 4.0Aaron L.View Answer on Stackoverflow
Solution 11 - C# 4.0user6469927View Answer on Stackoverflow