none
構造体の設計 RRS feed

  • 質問

  • 皆様お疲れ様です。
    先日の質問に引き続き、また .NET クラスライブラリの設計 に関して質問させてください。<(_ _)>

    第4章 型の設計のガイドライン 4.7 構造体の設計 の項を読んでいて、少し混乱してきました。

    問題の箇所にはこう書いてあります。

    DO 全てのインスタンスデータが 0、false、または null(のうち適切ないずれか)である状態が正しい状態であることを保証します。

    これによって構造体の配列が作成されたときに、予期しない不正なインスタンスが作成されることを防ぎます。たとえば以下の構造体は正しく設計されていません、パラメータを持つコンストラクタは正しい状態を保証しますが、構造体の配列が作成されたときにはこのコンストラクタは実行されず、したがってインスタンスはこの型にとって不正な値である 0 に初期化された値となります。

    // 悪い設計。クラス名を本のサンプルから変更した
    public struct BadPositiveInteger {
    
        int value;
    
        public BadPositiveInteger(int value) {
            if (value <= 0) throw new ArgumentException("...");
            this.value = value;
        }
    
        public override string ToString() {
            return value.ToString();
        }
    }
    

    この問題は既定の状態 (このケースでは value フィールドが 0 に等しい場合) が型に対して正しい論理状態であることを保証することにより修正可能です。

    // よい設計。こちらもクラス名を本のサンプルから変更した
    public struct GoodPositiveInteger {
    
        int value; // 論理値は value + 1
    
        public GoodPositiveInteger(int value) {
            if (value <= 0) throw new ArgumentException("...");
            this.value = value - 1;
        }
    
        public override string ToString() {
            return (value + 1).ToString();
        }
    }
    



    ガイドラインの言わんとすることは判らなくはありませんが、上記サンプルを見てて判らなくなりました。
    前者の BadPositiveInteger は悪い例として捉えることはできても、
    後者の GoodPositiveInteger が良い設計というのは何とも納得がいきません。

    実際以下のコードを実行すると、0 が10個出力されるだけです。

    class Program {
        static void Main(string[] args) {
    
            BadPositiveInteger[] badArray = new BadPositiveInteger[5];
            foreach (var c in badArray) {
                Console.WriteLine(c.ToString());
            }
    
            GoodPositiveInteger[] goodArray = new GoodPositiveInteger[5];
            foreach (var c in badArray) {
                Console.WriteLine(c.ToString());
            }
            Console.ReadKey();
        }
    }
    


    まだ、クラス ライブラリ開発のデザイン ガイドラインのサンプル の方が納得いくのですが、ここはどのように捉えるべきなのでしょうか?それとも本のサンプルが適切でないだけ?

    2010年1月23日 11:00
    モデレータ

回答

  • > インスタンスはこの型にとって不正な値である 0 に初期化された値となります。



    > この問題は既定の状態 (このケースでは value フィールドが 0 に等しい場合) が型に対して正しい論理状態であることを保証することにより修正可能です。
    BadPositiveInteger はフィールド変数が 0 であることで、本来あり得ない値を出力します。
    このため、フィールド変数に 0 が入ることは不正になります。(前者の文が示唆するもの)

    GoodPositiveInteger はフィールド変数が 0 であっても、本来あり得る値(0 より大きい)である 1 を出力します。
    このため、フィールド変数に 0 が入っても正しい論理状態と言えます。(後者の文が示唆するもの)


    フィールド変数が 0 で初期化されても、問題ないように作れと言っているだけですよね。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年1月23日 12:07
    モデレータ

すべての返信

  • 両方のループで badArray を foreach してますけど?
    2010年1月23日 11:08
  • 両方のループで badArray を foreach してますけど?

    うを!思い切り外してしまいました。orz

            GoodPositiveInteger[] goodArray = new GoodPositiveInteger[5];
            foreach (var c in goodArray) {
                Console.WriteLine(c.ToString());
            }
    これで全ての出力は 1 になりますね。失礼しました。<(_ _;)>
    でもこのサンプル、何かしっくり来ないんですよね。

    > インスタンスはこの型にとって不正な値である 0 に初期化された値となります。



    > この問題は既定の状態 (このケースでは value フィールドが 0 に等しい場合) が型に対して正しい論理状態であることを保証することにより修正可能です。

    矛盾しているように思えるのは気のせい?(^^;
    2010年1月23日 11:19
    モデレータ
  • > インスタンスはこの型にとって不正な値である 0 に初期化された値となります。



    > この問題は既定の状態 (このケースでは value フィールドが 0 に等しい場合) が型に対して正しい論理状態であることを保証することにより修正可能です。
    BadPositiveInteger はフィールド変数が 0 であることで、本来あり得ない値を出力します。
    このため、フィールド変数に 0 が入ることは不正になります。(前者の文が示唆するもの)

    GoodPositiveInteger はフィールド変数が 0 であっても、本来あり得る値(0 より大きい)である 1 を出力します。
    このため、フィールド変数に 0 が入っても正しい論理状態と言えます。(後者の文が示唆するもの)


    フィールド変数が 0 で初期化されても、問題ないように作れと言っているだけですよね。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年1月23日 12:07
    モデレータ
  • 愚問にお付き合いいただき有難うございます。<(_ _;)>

    > フィールド変数が 0 で初期化されても、問題ないように作れと言っているだけですよね。

    なるほど・・・(-ω-;)  ここの内容は結局、

    「構造体の配列が作成されても、予期しない不正なデータが作成されないよう実装すべし」

    という理解でいいのですね、

    ちなみに、クラス ライブラリ開発のデザイン ガイドラインでは

    すべてのインスタンス データが必要に応じて、ゼロ、false、または null に設定される状態が有効であることを確認してください。

    またエキサイト翻訳で英文を翻訳したら(少し修正)

    すべてのインスタンスデータがゼロ, false, またはヌルに設定される状態が確実に(適宜)有効になるようにしてください。

    とあるので、少し考えてしまいました。。。

    2010年1月23日 14:43
    モデレータ