114

我正在打电话:

myResult = MakeMyCall(inputParams, out messages);

但我实际上并不关心这些消息。如果它是一个输入参数,我不在乎,我只是传入一个空值。如果是我不在乎的回报,我就放弃它。

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

4

8 回答 8

128

从 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/

于 2016-11-30T13:49:48.210 回答
38

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

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

于 2009-01-20T17:20:46.833 回答
37

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

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

String Other_MakeMyCall(String inputParams)
{
    String messages;

    return MakeMyCall(inputParams, out messages);
}

然后你可以调用Other_MakeMyCall而不必摆弄out你不需要的参数。

于 2009-01-20T17:09:15.423 回答
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 参数可选的重载。

于 2009-01-20T18:59:36.590 回答
4

Visual Basic 编译器通过创建一个虚拟变量来做到这一点。C# 可以做到,如果你能说服微软这是一个好主意。

于 2009-01-20T17:28:30.190 回答
0

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

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

一旦出using块,messages将被自动处置。

于 2009-01-20T17:12:06.430 回答
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.
于 2009-01-20T17:28:04.417 回答
0

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

//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);
于 2017-11-03T12:01:57.493 回答