如何明确地抛弃一个参数?

时间:2009-01-20 17:06:12

标签: c# out

我正在打电话:

myResult = MakeMyCall(inputParams, out messages);

但我实际上并不关心这些消息。如果它是一个输入参数我不关心我只是传入一个null。如果是回归我不关心我只是把它关掉。

有没有办法用out做类似的事情,或者我是否需要声明一个我将忽略的变量?

8 个答案:

答案 0 :(得分:69)

从C#7.0开始,可以避免预先输出参数并忽略它们。

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

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

答案 1 :(得分:37)

您必须声明一个您将忽略的变量。最常见的情况是TryParse(或TryWhatever)模式,当它用于测试用户输入的有效性时(例如,它可以解析为数字吗?)而不关心实际的解析值。

你在问题​​中使用了“dispose”这个词,我怀疑这是不幸的 - 但是如果out参数是一个实现IDisposable的类型,你当然应该调用Dispose,除非方法文档明确指出接收值没有不授予所有权。我不记得曾经看过一个带有一次性out参数的方法,所以我希望这只是一个不吉利的选择。

答案 2 :(得分:36)

不幸的是,您需要传递一些东西,因为需要设置它的方法。所以你不能发送null,因为设置它的方法会爆炸。

隐藏丑陋的一种方法是将方法包装在另一个为您执行out参数的方法中:

String Other_MakeMyCall(String inputParams)
{
    String messages;

    return MakeMyCall(inputParams, out messages);
}

然后,您可以拨打Other_MakeMyCall,而不必使用您不需要的out参数。

答案 3 :(得分:11)

如果原始函数声明如下:

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

您可以声明这样的扩展方法:

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

扩展方法的行为类似于使out参数可选的重载。

答案 4 :(得分:4)

Visual Basic编译器通过创建虚拟变量来完成此操作。如果你能说服微软一个好主意,C#就可以做到。

答案 5 :(得分:0)

如果messages的类实现IDisposable,则不应忽略它。考虑类似下面的方法(可能在语法上不正确,因为我有一段时间没有编写C#):

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

一旦在using区块之外,messages将自动处理。

答案 6 :(得分:0)

您必须为out参数传递变量。在传递变量之前,您不必初始化变量:

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

通常,您可以在调用后忽略“消息” - 除非出于某种原因需要处置“消息”,例如使用有限的系统资源,在这种情况下您应该调用Dispose():

messages.Dispose();

如果它可能使用大量内存并且它将在一段时间内保持在范围内,如果它是引用类型则应该设置为null,如果它是值类型则应该设置为新的默认实例,所以垃圾收集器可以回收内存:

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

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

答案 7 :(得分:0)

在这种情况下,我为ConcurrentDictionary创建了一个没有Delete或Remove方法的通用扩展方法。

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

从ConcurrentDictionary的实例调用时:

ClientList.TryRemoveIgnore(client.ClientId);