C# 4.0 optional out/ref arguments

117,556

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 or out 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.

Share:
117,556

Related videos on Youtube

user3156301
Author by

user3156301

Updated on April 22, 2022

Comments

  • user3156301
    user3156301 about 2 years

    Does C# 4.0 allow optional out or ref arguments?

    • Andy Dent
      Andy Dent about 14 years
      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.
    • Roman Starkov
      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
      Adam Tolley over 13 years
      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.
    • Ricardo Gomes
      Ricardo Gomes over 13 years
      C# doesn't, but VB.NET does.
    • Dan Lugg
      Dan Lugg over 12 years
      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.
    • Tony
      Tony almost 10 years
      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.
  • Louis Rhys
    Louis Rhys almost 12 years
    any idea for more elegant solution than declaring temp/dummy?
  • Neutrino
    Neutrino over 10 years
    What's not elegant about that? Looks perfectly decent to me.
  • Ken Smith
    Ken Smith about 10 years
    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.
  • o0'.
    o0'. almost 10 years
    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.
  • zumalifeguard
    zumalifeguard over 9 years
    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.
  • Arturo Torres Sánchez
    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
    techspider about 8 years
    Please add some explanation on your code to make everyone understand the concept easily
  • Toby Speight
    Toby Speight about 8 years
    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.
  • Oskar
    Oskar over 7 years
    Hold 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
    Nathan Montez over 7 years
    This will result in a syntax error as method has void return type. Also, does not answer question.
  • ToolmakerSteve
    ToolmakerSteve about 7 years
    C# ignores the [Optional] annotation. This does not help.
  • Reiner
    Reiner over 6 years
    In C# 7.0 you can use a temporary write-only variable like: return SomeMethod(out _);
  • Onur Topal
    Onur Topal over 5 years
    is it _ or * "p.GetCoordinates(out int x, out *); // I only care about x"
  • Onur Topal
    Onur Topal over 5 years
    looks like I was looking an older version of the document.
  • Brain2000
    Brain2000 about 5 years
    If you have multiple optional out parameters, you still end up with a cartesian product set of overloads.
  • Dunc
    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
    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
    Chad over 4 years
    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
  • JohnC
    JohnC over 3 years
    Can someone please elaborate on this: "the compiler won't enforce the requirement that the out parameter be assigned before exiting the method"?
  • Robin R
    Robin R over 3 years
    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.
  • Paul Childs
    Paul Childs over 3 years
    If the compiler complained then it would not be optional.
  • Paul Childs
    Paul Childs over 3 years
    Discards 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
    Matt over 2 years
    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!
  • Brain2000
    Brain2000 over 2 years
    Not if you have 10 optional ref parameters. Then you have a giant mess when trying to port to C#
  • Brain2000
    Brain2000 over 2 years
    Why can't the discard be automatic like it is in VB.net?