2

.NETチームが(ソースを見つけます...)プリミティブ型の解析メソッドの設計を後悔していると述べていることを考えると(たとえばInt32.TryParse(String s, out Int32 result))、なぜこれらはより明白でクライアントフレンドリーなバリアントで更新されていないのですか?

フレームワークバージョン:

Int32? numValue;
Int32 placeHolder;
if (! Int32.TryParse("not a number", out placeHolder))
    numValue = 10;

改善されたバージョン:

var numValue = Int32.Parse("not a number", 10);

改善された解析方法の署名は次のとおりです。

public static Int32? Parse(String s, Int32? defaultValue = null);

そして、それは以下の素朴な実装を持っているかもしれません:

public static Int32? Parse(String s, Int32? defaultValue = null) {
    Int32 temp;
    return ! Int32.TryParse(s, out temp)
        ? defaultValue
        : temp;
}
4

2 に答える 2

2

この署名:

public static Int32? Parse(String s, Int32? defaultValue = null);

Parse(string s)オプションの引数が指定されていない場合、それらを区別する方法がないため、既存のオーバーロードと競合します。既存のコードとの互換性が失われるため、既存のメソッドが変更または削除されることはおそらくありません。

ただし、パラメータTryParseをとらないオーバーロードを作成することは可能です。out int value

public static int? TryParse(string s)

デフォルト値のパラメーターを追加する必要はないことに注意してください。代わりに、null合体演算子を使用できます。

string s = ...
int value = int.TryParse(s) ?? 0;
于 2013-02-05T13:07:43.323 に答える
2

BCLチームの誰かが話すべき話を持っていない限り、これに対する決定的な答えがあるかどうかはわかりません。

いくつかの考慮事項は次のとおりです。

  1. メソッドを変更すると、既存のコードベースに大きな重大な変更が加えられ、利益はほとんどありません(議論の余地があります)。以下の理由により、それは不利益になると主張する人もいるかもしれません。
  2. null許容型ボックスは、基礎となる値をラップラップして、解析が成功すると予想し、null許容型が必要ない場合でも、常に(マイナーな)パフォーマンスヒットを引き起こします。
  3. 入力が有効であることがわかっいる場合、入力が無効であるという例外的なケースParseに対して、 メソッドは例外をスローします。これは、必要のないときのための追加のエラー処理コードがなく、設計の観点から期待されるため、一般的にパフォーマンスが高くなります。無効なケースを処理することを計画している場合は、それが目的です。TryParse
  4. int Parse(string, int? defaultValue)との間の混乱int Parse(string)、主にそれらのエラー処理に関して。最初のメソッドのオプション部分を削除したことに注意してください。そうしないと、両方のメソッドを使用しても意味がありません(明示的に渡さずにメソッドを呼び出すことはできませんnull)。この時点では、一方のオーバーロードが失敗時に例外をスローし、もう一方はスローしないため、少し混乱します。Type.GetTypeなど、これにはいくつかの例外がありますが、 一般的にはまれであり、そのような場合は、例外をスローするかどうか示す明示的に名前が付けられたパラメーターを使用します。
  5. 設計どおりのもう1つの利点はTryParse、合格/不合格の結果を処理するためのAPIによって非常に明示的であるということです。null失敗を示すマジックナンバー/結果( )ではなく、個別のtrue/false値を返します。現在、一部のメカニズムはこれを実行するため(String.IndexOfたとえば、-1を返す)、これが良いことなのか悪いことなのかは議論の余地があります。練習によっては、戻りtrue/false値を使用する方が簡単な場合もあれば、魔法のnull結果を使用する方が簡単な場合もあります。しかし、彼らは、まったく同じことを行うが、署名/戻り値がわずかに異なる2つの方法で、水を濁さないことを決定しました。
  6. もう1つの考慮事項は、null許容値型がどれほど一般的かということです。あなたは本当にInt32?多くの場所で使用していますか?それとも、エラー/入力処理のためだけですか?私の経験では、null許容値は にデータベースI / Oに使用されます(それでも、それほど頻繁ではありません)。他の唯一の時間は、最初のインターフェースのためだけである、信頼されていないソースからの入力のためである可能性があります。基礎となるすべてのコードは、null許容ではないものに対して引き続き入力されInt32ます。このような場合、元の2つの方法があります。

    int input;
    if (TryParse(someString, out input))
        DoSomethingValid(input); //valid! Do something
    else
        ErrorMessage()//not valid, error!
    

    またはあなたの提案:

    int? input = Parse(someString)
    if (input != null)
        DoSomethingValid(input.GetValueOrDefault())//valid! Do something
    else
        ErrorMessage()//not valid, error!
    

    両方がどれほどているかに注意してください。あなたの提案は、この場合にはほとんど何も提供しません。また、の使用法にも注意してください GetValueOrDefault()。これは、null以外であることがわかっている場合、実際にはラップされた値にアクセスするためのより高速で優れた方法ですが、アクセサーを介して使用されることはめったにありません(少なくともインターネットで見たものから)Value 。あなたが提案するようにBCLが方法を追加/変更した場合、多くの人が不必要にアクセサーを攻撃するだろうParseと思います。Value

    アプリケーションの設計やそのレイヤー全体でnull許容値を大幅に使用しているケースについて具体的にコメントすることはできませんが、私の経験では、それらはめったに使用されないか、めったに使用されるべきではありません(私にとって、それはほぼ「文字通り」のレベルのコードの臭いです-タイプされた"データ)

最終的に、拡張メソッドが(Linqを除いて)追加された理由の一部は、ユーザーが必要に応じて独自のAPIをロールできるようにするためだったと思います。あなたの場合、あなたは簡単にあなたが望む構文を得るために拡張メソッドを追加することができます:

public static Int32? Parse(this String s, Int32? defaultValue = null)
{
    Int32 temp;
    return !Int32.TryParse(s, out temp)
        ? defaultValue
        : temp;
}

string validString = "1";
int? parsed = validString.Parse(); //1
int? failParsed = "asdf".Parse(9); //9

チームは通常、現状を維持することを好み、追加はシステムに追加するのに十分な大きなメリットを提供する必要があります。また、チームはAPIに既存の回避策をそのまま検討します。拡張メソッドオプションを考えると、APIの重要な破壊的性質を考慮して、APIを変更することはそれほど大きな問題ではないことをお勧めします。

于 2013-02-05T13:19:56.483 に答える