web-dev-qa-db-ja.com

out引数を明示的に破棄する方法は?

私は電話をかけています:

myResult = MakeMyCall(inputParams, out messages);

しかし、私は実際にメッセージを気にしません。それが入力パラメーターである場合、私は気にしませんでしたが、nullを渡すだけです。それが帰りだったら、私は気にしませんでした。

Outで同様のことを行う方法はありますか、それとも無視する変数を宣言する必要がありますか?

81
Andrew Ducker

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/

74
Nolonar

無視する変数を宣言する必要があります。これは、実際に解析された値を気にせずにユーザー入力の妥当性をテストするために使用される場合(たとえば、数値として解析できる場合)、TryParse(またはTryWhatever)パターンの最も一般的なケースです。

質問で「dispose」という単語を使用しましたが、残念ですが、outパラメータがIDisposableを実装する型である場合、メソッドのドキュメントで値の受信が授与されないことが明示されていない限り、Disposeを呼び出す必要があります所有権。しかし、使い捨てのoutパラメーターを使用したメソッドを見たことを覚えていないので、これが単なる不幸な選択であったことを願っています。

37
Jon Skeet

残念ながら、メソッドは設定する必要があるため、何かを渡す必要があります。したがって、nullを送信することはできません。設定する必要があるメソッドが爆破するためです。

さを隠す1つの方法は、outパラメーターを実行する別のメソッドでメソッドをラップすることです。

String Other_MakeMyCall(String inputParams)
{
    String messages;

    return MakeMyCall(inputParams, out messages);
}

その後、不要なoutパラメーターをいじる必要なく、Other_MakeMyCallを呼び出すことができます。

36
Andrew Hare

元の関数が次のように宣言されている場合:

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パラメーターをオプションにするオーバーロードのように動作します。

11
bmm6o

Visual Basicコンパイラは、ダミー変数を作成してこれを行います。 Microsoftに良いアイデアを納得させることができれば、C#でそれを行うことができます。

4
Jonathan Allen

この場合、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);
0
flodis

messagesのクラスがIDisposableを実装している場合、無視しないでください。次のアプローチのようなものを検討してください(私はしばらくC#を書いていないので、構文的には正しくないかもしれません):

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

usingブロックの外に出ると、messagesは自動的に破棄されます。

0
Sören Kuklau

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.
0
Joe Erickson