2009-08-26 28 views
3

"C#Class Desing Handbook"(Pg 137)のサンプルクラスは、クラスのみのコンストラクタの中から特定のフィールドのクラス検証メソッドを呼び出しません。したがって、基本的にサンプルクラスを使用すると、不正なデータを持つオブジェクトを作成し、検証を行うフィールドのプロパティを呼び出すときにそのデータに対してエラーをスローするだけです。だからあなたは今、悪いものを持っていて、事実の後まで知ることはできません。コンストラクタデータを検証する

初期化時に不正なデータが見つかった場合に、コンストラクタからプロパティを呼び出すだけでエラーが発生するのはなぜですか?

私のコンストラクタから自分のプロパティを呼び出すと、次のようなフォーマットが使用される傾向があります。これは、初期化データを検証するための適切な構造ですか? TY

class Foo 
{ 
    private string _emailAddress; 

    public Foo(string emailAddress) 
    { 
     EmailAddress = emailAddress; 
    } 

    public string EmailAddress 
    { 
     get { return _emailAddress; } 
     set 
     { 
      if (!ValidEmail(value)) 
       throw new ArgumentException 
        (string.Format 
        ("Email address {0} is in wrong format", 
        value)); 

      _emailAddress = value; 
     } 
    } 


    private static bool ValidEmail(string emailAddress) 
    { 
     return Regex.IsMatch 
      (emailAddress, @"\b[A-Z0-9._%+-]+" + 
          @"@[A-Z0-9.-]+\.[A-Z]{2,4}\b", 
          RegexOptions.IgnoreCase); 
    } 
} 
+0

これはおそらくコミュニティ質問であるべきです - もし誰かがそれを正しく設定してください。 – user10178

答えて

2

EMAILADDRESSは、任意のレベルでnullの場合は、チェックされていないので、まあ、1のために、あなたは、恐ろしいとNullReferenceExceptionを取得する可能性があります。この特定のチェックはコンストラクタ自体で実行する必要があり、emailAddressがnullの場合はArgumentNullExceptionをスローします。残りの部分については、あなたのサンプルに書かれているように、特に問題はありません。ただし、プロパティを仮想化してこのクラスから子を派生させると、いくつかの問題が発生する可能性があります。フィールド初期化、基本クラス、派生クラスのコンストラクタの実行順序が問題になり、注意が必要です。

+0

私はそれを明確にするために残しましたが、はい、ありがとうございました。 – user10178

+0

あなたは大歓迎です。 :) – jrista

0

このアプローチでは何も問題ありません。コンストラクタ内でこのメソッドを呼び出すことができます。プロパティのsetter/getterは、メソッド呼び出しの文法的な砂糖です。

+0

電子メールアドレスがコンストラクタで設定されている場合とプロパティ設定ツールで設定されている場合は、クラスの動作が異なります。一貫性のない振る舞いは良い設計プロパティではありません:-)例コードでは –

+0

です。質問者はコンストラクタが私が知る限りプロパティセッターを使用しているので、振る舞いは実際は一貫しています。私は行方不明のものがありますか? – Kevlar

2

はい、あなたの一般的なアプローチがある場合:

すると、だけにして、私はそれを愛する

validオブジェクトのインスタンスを取得することができていることを確認してください。

コンストラクタに入れるべきもののために、単に「コンテナ」を作成するのではなく、すぐに有効なオブジェクトを作成するために使用されなければならない。

+0

はい、有効なオブジェクトだけを得ることはここのアイデアです。コンストラクタのオーバーロードを追加して、ユーザーが空白のフィールドを入力できるようにします。 ty。 – user10178

0

メールアドレスが設定されているとき、検証が起こっています。これは後で電子メールアドレスを再設定する可能性があるため、必要な場所です。

コンストラクタで検証とも呼ばれる場合は、追加の冗長な検証呼び出しを行います(構築時には1回、コンストラクタでは電子メールアドレスが設定されている場合はもう1回)。

+0

?電子メールアドレスの元の設定は、_emailsのプロパティを呼び出すコンストラクタ内にあります。私がただ_emailを直接設定した場合、悪い電子メールが渡された場合、オブジェクトが不正になります。オブジェクトがインスタンス化された後にプロパティが変更された場合のみ検証されます。 – user10178

+0

コンストラクタがプロパティのセッターを呼び出しています: "EmailAddress" – apiguy

+0

はい、わかりました - 私はそれを書きました。私が理解できなかったことはあなたがコメントしていたことです...ごめんなさい。 – user10178

2

コンストラクタ内のデータを検証しないことは意味がありません。あなたが指摘しているように、オブジェクトは無効な状態になる可能性があります。この設計を考えると、ゲッターを呼び出すときに悪いデータがあることに気付かないでしょう。

中度以上のものについては、すぐに例外をスローするのではなく、壊れたルールのアプローチを使用する傾向があります。このアプローチでは、無効なクラスとプロパティに関する情報と無効な理由を含むBrokenRulesオブジェクトを定義します。次に、共通の基底クラスで、オブジェクトの「間違った」すべてのリストを保持するListを定義します。 (ベースクラスの)プロパティであるIsValidは、現在破損しているルールがあるかどうかを示します。

この利点は、オブジェクト状態にいくつかの問題がある可能性があることです。ユーザーが問題を解決するように求められている場合(つまり、このオブジェクトはUIから設定されます)、すべての問題のリストを提供することで、ユーザーは1つのエラーを修正するのではなく、1つのエラーを修正することができます。もう一つ。等

+0

ありがとうエリック - 私は壊れたルールのアプローチを見てみましょう!フレームワークを構築し、まだ学習し始めたばかりです。私は爆発的なフレームワーク設計ガイドラインを拾いました!素晴らしい本。 – user10178

関連する問題