Question

I'm making a call:

myResult = MakeMyCall(inputParams, out messages);

but I don't actually care about the messages. If it was an input parameter I didn't care about I'd just pass in a null. If it was the return I didn't care about I'd just leave it off.

Is there a way to do something similar with an out, or do I need to declare a variable that I will then ignore?

Was it helpful?

Solution

Starting with C# 7.0, it is possible to avoid predeclaring out parameters as well as ignoring them.

public void PrintCoordinates(Point p)
{
    p.GetCoordinates(out int x, out int y);
    WriteLine($"({x}, {y})");
}

public void PrintXCoordinate(Point p)
{
    p.GetCoordinates(out int x, out _); // I only care about x
    WriteLine($"{x}");
}

Source: https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/

OTHER TIPS

You have to declare a variable which you will then ignore. This is most commonly the case with the TryParse (or TryWhatever) pattern, when it is used to test the validity of user input (e.g. can it be parsed as a number?) without caring about the actual parsed value.

You used the word "dispose" in the question, which I suspect was just unfortunate - but if the out parameter is of a type which implements IDisposable, you should certainly call Dispose unless the method documentation explicitly states that receiving the value doesn't confer ownership. I can't remember ever seeing a method with a disposable out parameter though, so I'm hoping this was just an unlucky choice of words.

Unfortunately you are required to pass something because the method is required to set it. So you cannot send null because the method, being required to set it, would blow up.

One approach to hide the ugliness would be to wrap the method in another method that does the out parameter for you like so:

String Other_MakeMyCall(String inputParams)
{
    String messages;

    return MakeMyCall(inputParams, out messages);
}

Then you can call Other_MakeMyCall without having to fiddle with out parameters you don't need.

If the original function is declared like this:

class C
{
    public Result MakeMyCall(Object arg, out List<String> messages);
}

You can declare an extension method like this:

static class CExtension
{
    public static Result MakeMyCall(this C obj, Object arg)
    {
        List<String> unused;
        return obj.MakeMyCall(arg, out unused);
    }
}

The extension method will behave like an overload that makes the out parameter optional.

The Visual Basic compiler does this by creating a dummy variable. C# could do it, if you can convince Microsoft its a good idea.

If the class of messages implements IDisposable, you shouldn't ignore it. Consider something like the following approach (may not be syntactically correct since I haven't written C# in a while):

using (FooClass messages) {
    myResult = MakeMyCall(inputParams, messages);
}

Once outside the using block, messages will be disposed automatically.

You must pass a variable for the out parameter. You do not have to initialize the variable before passing it:

MyMessagesType messages;
myResult = MakeMyCall(inputParams, out messages); 

Typically, you can just ignore 'messages' after the call - unless 'messages' needs disposing for some reason, such as the use of limited system resources, in which case you should call Dispose():

messages.Dispose();

If it might use a significant amount of memory and it is going to remain in scope for a while, it should probably be set to null if it is a reference type or to a new default instance if it's a value type, so that the garbage collector can reclaim the memory:

messages = null; // Allow GC to reclaim memory for reference type.

messages = new MyMessageType(); // Allow GC to reclaim memory for value type.

In this case I made an generic extension method for ConcurrentDictionary that has no Delete or Remove method.

//Remove item from list and ignore reference to removed item
public static void TryRemoveIgnore<K,T>(this ConcurrentDictionary<K,T> dictionary, K key)
{
    T CompletelyIgnored;
    dictionary.TryRemove(key, out CompletelyIgnored);
}

When called from an instance of ConcurrentDictionary:

ClientList.TryRemoveIgnore(client.ClientId);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top