質問

出力パラメーターをいつ使用する必要があるのか​​理解できません。複数の型を返す必要がある場合は、個人的に結果を新しい型でラップします。out よりも作業がはるかに簡単であることがわかります。

このような方法を見たことがありますが、

   public void Do(int arg1, int arg2, out int result)

それが実際に意味があるケースはありますか?

どうですか TryParse, を返さないのはなぜですか ParseResult タイプ?それとも新しいフレームワークでは null 許容型を返しますか?

役に立ちましたか?

解決

あなたはTryNNN機能を持っており、それがアウトパラメータは、常に関数が成功しない場合でも、設定されることは明らかだとき

アウトが良いです。これは、あなたが宣言ローカル変数はnullを照らし合わせて、コードの後半にチェックを配置するのではなく設定されているという事実に頼ることができます。 (以下のコメントは、パラメータがnullするように設定することができることを示しているので、あなたはこれが事実であるかどう確認するために呼び出している関数のドキュメントを確認することをお勧めします。)これは、コードが少し明確かつ容易になります読み取ります。あなたのような方法の条件にいくつかのデータとステータスを返すために必要がある場合、別の場合は、次のとおりです。

public bool DoSomething(int arg1, out string result);
関数が成功し、その結果を出力パラメータに格納されている場合、

この場合、リターンが示すことができます。確かに、あなたは関数が単にstringを返す方法を設計することができますので、この例は不自然ですが、あなたのアイデアを得る。

欠点は、あなたがそれらを使用するローカル変数を宣言する必要があることです。

string result;
if (DoSomething(5, out result))
    UpdateWithResult(result);

の代わりに:

UpdateWithResult(DoSomething(5));

しかし、それにも不利ではないかもしれないが、それはあなたが行っている設計に依存します。日時の場合には、両方の手段(解析とTryParse)が設けられている。

他のヒント

ほとんどのことと同様、それは状況によります。オプションを見てみましょう

  • 関数の戻り値として何でも返すことができます
  • 複数の値を返したい場合、または関数にすでに戻り値がある場合は、out params を使用するか、これらすべての値をプロパティとして公開する新しい複合型を作成します。

TryParse の場合、out パラメータを使用するのが効率的です。(32b マシンの場合) 16B のオーバーヘッドとなる新しい型を作成したり、呼び出し後にガベージ コレクションを実行するパフォーマンス コストを負担したりする必要はありません。TryParse は、たとえばループ内から呼び出すことができるため、ここで out params ルールを設定します。
ループ内で呼び出されない関数の場合 (つまり、パフォーマンスは大きな問題ではありません)、単一の複合オブジェクトを返す方が「クリーン」になる可能性があります (見る人の主観的)。匿名型が追加されました と ダイナミックタイピング を使えば、さらに簡単になるかもしれません。

注記:

  1. out params には従う必要のあるいくつかのルールがあります。コンパイラは、関数が終了する前に値を初期化することを保証します。したがって、TryParse は、解析操作が失敗した場合でも、出力パラメータを何らかの値に設定する必要があります。
  2. TryXXX パターンは、どのような場合にパラメータを使用するかを示す良い例です。Int32.TryParse は、解析が失敗したかどうかを知るために例外をキャッチするパフォーマンス ヒットについて苦情が寄せられたため、導入されました。また、解析が成功した場合に行う可能性が最も高いのは、解析された値を取得することです。out パラメータを使用すると、Parse への別のメソッド呼び出しを行う必要がなくなります。

私はTryParseのようなあなたがブールと値の両方を返すために必要がある場合に有用ですが、コンパイラはこのような何かをできるようになるならば、それはいいだろうアウトだと思います

bool isValid = int.TryParse("100", out int result = 0);

間違いなく、out パラメーターは、投稿した例のように、複数の値を返す必要があるメソッドがある場合に使用することを目的としています。

public void Do(int arg1, int arg2, out int result)

out パラメータを使用することはあまり意味がありません。1 つの値しか返さないためです。out パラメータを削除して int 戻り値を入れた方が、このメソッドをより適切に使用できます。

public int Do(int arg1, int arg2)

out パラメータにはいくつかの良い点があります。

  1. 出力パラメータは、最初は未割り当てとみなされます。
    • すべての出力パラメータ しなければならない メソッドが戻る前に確実に割り当てを行う必要があるため、割り当てを見逃した場合、コードはコンパイルされません。

結論として、私は基本的にパラメータを使用しようとします プライベートAPI 複数の戻り値をラップするために別の型を作成することを避けるため、私のパブリック API では、TryParse パターンと一致するメソッドでのみそれらを使用します。

年後半の答えと、私は知っています。 あなたが返すように、新しいオブジェクトをインスタンス化しない、あなたの方法を希望していないかどうかは(とref同様)にも本当に便利です。これは、あなたの方法のためのサブマイクロ秒のパフォーマンスを実現したい高性能システムに非常に関連性があります。インスタンス化は、メモリアクセスの観点から見て比較的高価である。

単に値を返すためにタイプを作成するには、:-)私には少し痛い聞こえます まず、私はそれを必要とする実際の変数に返すタイプから値を割り当てる必要があり、呼び出し元のメソッドにその値を返すための型を作成する必要があります。

アウトパラメータを使用するのsimiplerされます。

はい、それは意味を成しません。例えばこれを持っています。

String strNum = "-1";
Int32 outNum;

if (Int32.TryParse(strNum, out outNum)) {
    // success
}
else {
    // fail
}

操作は、戻り値の正常な機能に障害が発生した場合、あなたが何を返すことができますか?あなたは最も確かに返すことができませんでした-1失敗表すために、その後、フェイル戻り値として始めるために解析されていた実際の値の間には区別はないだろうからです。我々はそれが成功したかどうかを確認するためにブール値を返し、それが、その後なかった場合、我々は安全にすでに割り当てられている私たちの「戻り」の値を持っている理由はここにあります。

これは、私がTryParse関数の出力パラメータにnullを渡すことができない私を困らせています。

それでも、私は二つのデータを新しい型を返すにいくつかのケースでそれを好みます。大部分または1つのピースが一瞬だけ後に単一の操作のために必要とされるため、それらは無関係だ場合は特に。私は本当に私がに対処する必要が出てパラメータではなく、いくつかのランダムResultAndValueクラスを持つようなTryParse関数の結果の値を保存する必要がないときます。

常に型を作成すると、アプリケーション内が非常に乱雑になる可能性があります。

ここで述べたように、典型的な使用例の 1 つは次のとおりです。 TrySomething 成功の指標としてブール値を返し、その後実際の値を返すメソッド。また、if ステートメントが少しすっきりしていることもわかりました。いずれにせよ、3 つのオプションはすべてほぼ同じ LOC を持っています。

int myoutvalue;
if(int.TryParse("213",out myoutvalue){
    DoSomethingWith(myoutvalue);
}

vs.

ParseResult<int> myoutvalue = int.TryParse("213");
if ( myoutvalue.Success ) {
    DoSomethingWith(myoutvalue.Value);
}

vs.

int? myoutvalue = int.TryParse("213");
if(myoutvalue.HasValue){
    DoSomethingWith(myoutvalue.Value);
}

「Nullable Type を返さない理由」については、次のようになります。TryParse は Framework 1.x から存在しますが、Nullable Types は 2.0 に付属しています (ジェネリックが必要なため)。では、なぜ不必要に互換性を壊したり、一部の型の TryParse 間で不一致を引き起こしたりするのでしょうか?いつでも独自の拡張メソッドを作成して、既存の機能を複製できます (「 エリック・リッパーツの投稿 何かをする/しないの背後にある何らかの理由を含む、無関係な主題について)

別の使用例は、複数の無関係な値を返さなければならない場合ですが、それを実行した場合、メソッドが実行しすぎている可能性があるというアラームがトリガーされるはずです。一方、メソッドが高価なデータベースや Web サービス呼び出しのようなもので、結果をキャッシュしたい場合は、そうするのが合理的かもしれません。もちろん、タイプを作成することもできますが、それはアプリケーション内にもう 1 つのタイプを作成することを意味します。

私は時々、読みやすくするために、のうちのパラメータを使用し、メソッド名を読み込むときには、メソッドの出力があり、特に返す結果に加えて、コマンドを実行する方法のために何よりも重要である。

StatusInfo a, b, c;

Initialize(out a);
Validate(a, out b);
Process(b, out c);

対ます。

StatusInfo a = Initialize();
StatusInfo b = Validate(a);
StatusInfo c = Process(b);

は、私にとっては少なくとも、私は私がスキャンしてる各行の最初の数文字に重点をたくさん入れました。私は簡単にいくつかの「StatusInfo」の変数が宣言されていることを承認した後の最初の例では何が起こっているのか伝えることができます。第2の例では、私が見る最初のものは、StatusInfoの束が取り出されることです。私は、メソッドが持つ効果の種類を確認するために二度目をスキャンする必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top