10

これは、C# で使用される規則に関連しています。

2 つのパラメーター (X 座標と Y 座標) を持つメソッドがあります。これらの座標は、「タイル」が存在する位置を表します。タイルがこれらの座標に存在する場合、メソッドはその番号を返します。これらの座標にタイルが存在しない場合、メソッドがどのように動作するのか疑問に思っています。

次の 3 つのオプションが表示されます。

  1. 例外を使用します。メソッドがタイルを見つけられないたびに、例外を発生させることがあります。ただし、このような状況はまれではないため、このオプションは最悪のオプションです。
  2. 昔ながらの C++ の方法で行い、タイルがない場合は -1 を返します。
  3. タイル番号を参照パラメーターにし、メソッドの戻り値の型を boolean に変更して、タイルの有無を示します。しかし、これは私には少し複雑に思えます。

それで、私は何をすべきですか?

4

12 に答える 12

23

null を返し、呼び出し元のコードでこれを確認できます。

もちろん、null 許容型を使用する必要があります。

int? i = YourMethodHere(x, y);
于 2009-06-05T17:20:40.977 に答える
20

-1 を返します。

これは単なる C++ の規則ではなく、.NET Framework でも一般的です。たとえば、String.IndexOf などのメソッドや、リストを表すコントロールの SelectedIndex などのプロパティです。

編集

詳しく説明すると、質問の 3 つのオプション (例外、戻り値 -1、出力パラメーター) のうち、-1 を返す方法が適しています。例外は例外的な状況のためのものであり、Microsoft コーディング ガイドラインでは、可能な場合はパラメータを避けることを推奨しています。

私の見解では、-1 を返す (常に無効な値になる場合)、null 許容の int を返す、または Tile オブジェクトを返すことはすべて許容される解決策であり、アプリの残りの部分と最も一貫性のあるものを選択する必要があります。開発者が次のいずれかで少しでも問題を抱えているとは想像できません。

int tileNumber = GetTile(x,y);
if  (tileNumber != -1)
{
   ... use tileNumber ...
}


int? result = GetTile(x,y);
if (result.HasValue)
{
    int tileNumber = result.Value; 
   ... use tileNumber ...
}


Tile tile = GetTile(x,y);
if (tile != null)
{
   ... use tile ...
}

「null許容型を返すよりもはるかに効率的」なintを使用することに関するPeter Rudermanのコメントを理解しているかどうかはわかりません。どんな違いも無視できると思っていたでしょう。

于 2009-06-05T17:21:38.853 に答える
17

例外は例外的なケースのためのものであるため、既知予想されるエラー状況で例外を使用することは「悪い」ことです。また、このエラー状況が発生することが予想されるため、特にこのエラーを処理するためにどこでも try-catch を使用する可能性が高くなります。

唯一のエラー条件 (-1 など) が実際の値と混同しやすい場合は、戻り値をパラメーターにすることができます。負のタイル番号を使用できる場合は、これがより良い方法です。

nullable int は参照パラメーターの代わりになる可能性がありますが、これを使用してオブジェクトを作成しているため、「エラー」がルーチンである場合、参照パラメーターよりもこの方法でより多くの作業を行う可能性があります。Roman が別の場所のコメントで指摘したように、C# と VB では、null 許容型の導入が遅すぎて、VB が C# のような優れたシンタックス シュガーを提供できないという問題が発生します。

タイルが非負にしかならない場合、-1 を返すことは許容され、エラーを示す伝統的な方法です。また、パフォーマンスとメモリの点で最も安価です。


他に考慮すべきことは、自己文書化です。-1 と例外を使用するのは慣習です。開発者がそれらを認識していることを確認するためにドキュメントを作成する必要があります。戻り値または参照パラメーターを使用するint?と、それ自体がより適切に自己記述され、開発者がエラー状況を処理する方法を知るためのドキュメントは必要ありません。もちろん :) 毎日歯を磨く方法と同じように、常にドキュメントを作成する必要があります。

于 2009-06-05T17:24:44.297 に答える
6

null 許容の戻り値を使用します。

int? GetTile(int x, int y) {
   if (...)
      return SomeValue;
   else
      return null;
}

これが最も明確な解決策です。

于 2009-06-05T17:23:47.260 に答える
3

メソッドが基になるタイル オブジェクトにアクセスできる場合、別の可能性として、タイル オブジェクト自体を返すか、そのようなタイルがない場合は null を返します。

于 2009-06-05T17:23:21.160 に答える
2

最良のオプションは、ブール値も返すか、nullを返すことです。

例えば

bool TryGetTile(int x, int y, out int tile);

また、

int? GetTile(int x, int y);

「TryGetValue」パターンを好む理由はいくつかあります。1つは、ブール値を返すため、クライアントコードは非常に単純です。例:if(TryGetValue(out someVal)){/ * some code*/}。これを、ハードコードされた番兵値の比較(-1、0、null、特定の例外セットのキャッチなど)を必要とするクライアントコードと比較してください。「マジックナンバー」はこれらの設計ですぐに発生し、密結合を除外すると次のようになります。雑用。

番兵の値、null、または例外が予想される場合は、使用されているメカニズムに関するドキュメントを確認することが絶対に不可欠です。ドキュメントが存在しないかアクセスできない場合、一般的なシナリオでは、他の証拠に基づいて推測する必要があります。間違った選択をした場合は、単にnull参照例外またはその他の悪い欠陥を設定しているだけです。一方、TryGetValue()パターンは、名前とメソッドのシグネチャだけで自己文書化に非常に近いものです。

于 2009-06-05T17:44:03.003 に答える
2

これはかなり一般的な C# のアプローチであるため、-1 を返すことができます。ただし、クリックされたタイルを実際に返し、タイルがクリックされなかった場合は、シングルトンの NullTile インスタンスへの参照を返す方がよい場合があります。このようにすることの利点は、返される各値に具体的な意味を与えることです。数値以外の本質的な意味を持たない数値であるだけではありません。タイプ「NullTile」は、その意味に関して非常に具体的であり、コードの他の読者に疑いの余地はほとんどありません。

于 2009-06-05T17:27:06.040 に答える
2

オプション 2 を使用します。そのとおりです。このような一般的なケースで例外をスローすると、パフォーマンスが低下する可能性があります。out パラメーターを使用して true または false を返すのは便利ですが、読むのは面倒です。

また、string.IndexOf()方法も考えてください。何も見つからない場合は、-1 を返します。私はその例に従います。

于 2009-06-05T17:25:05.653 に答える
1

私はあなたが尋ねた質問について私自身の意見を持っていますが、それは上に述べられており、私はそれに応じて投票しました。

あなたが尋ねなかった質問に関して、または少なくとも上記のすべての答えの拡張として:私はアプリ全体で一貫した同様の状況への解決策を維持することを確実にします。言い換えれば、あなたが決めた答えが何であれ、それをアプリ内で同じに保ちます。

于 2009-06-05T17:48:47.740 に答える
0

私はそれを2つの方法に分けます。とのようなものがCheckTileExists(x,y)ありGetTile(x,y)ます。前者は、指定された座標にタイルがあるかどうかを示すブール値を返します。2番目の方法は、基本的に元の投稿で話している方法ですが、無効な座標が与えられた場合に例外をスローする必要があります(これは、発信者が最初に電話CheckTileExists()をかけなかったことを示しているため、合法的に例外的な状況です。速度を上げるには、おそらくこれら2つのメソッドでキャッシュを共有する必要があります。これにより、次々に呼び出された場合に、GetTile()機能はごくわずかです。これらのメソッドを配置するのに適したオブジェクトがすでにあるかどうか、または新しいクラスで2つのメソッドを作成する必要があるかどうかはわかりません。私見では、このアプローチのパフォーマンスの低下はごくわずかであり、コードの明確さの向上はそれをはるかに上回っています。

于 2009-06-05T17:41:01.230 に答える
0

Tile座標で参照されるオブジェクトを作成した(または作成できた)可能性はありますか?その場合、そのタイルへの参照を返すことができます。またはnull、指定された座標にタイルがない場合は、次のようになります。

public Tile GetTile(int x, int y) {
    if (!TileExists(x, y)) 
        return null;
    // ... tile lookup here...
}
于 2009-06-05T17:43:07.747 に答える
0

メソッドが低レベル ライブラリの一部である場合、標準の .NET 設計では、メソッドから例外をスローするように指示されている可能性があります。

これは、.NET フレームワークが一般的にどのように機能するかです。上位レベルの呼び出し元は、例外をキャッチする必要があります。

ただし、UI イベントに応答しているため、パフォーマンスに影響を与える UI スレッドからこれを行っているように見えるため、Jay Riggs が既に提案したことを行い、null を返し、呼び出し元が null の戻り値を確認するようにします。

于 2009-06-05T17:23:41.380 に答える