none
プロパティのプロパティへのSet RRS feed

  • 質問


  • プロパティの動作がよくわかりません。
    変数ではないため、戻り値を設定できませんというエラーが発生します。
    以下のような場合もなると思うのですが、何が悪いのでしょうか?


    struct InfoKey
    {
        modifierKey modifier { get; set; }
        char keyCode{ get; set; }
        Keys key{ get; set; }
    }

    struct ModifierKey
    {
        bool isAlt;
        bool isShift;
        bool isCtrl;
    }


    こういったコードで次のようなことをするとエラーになってしまいます。

    InfoKey keys = new InfoKey();
    // 値を設定する例
    keys.modifierKey.isAlt = true; // <- エラー

    直接プロパティのmodifierKeyに、値を設定してあげると問題ないです。
    // 値を設定する例
    keys.modifierKey = new ModifierKey();


    ただ、後者は毎回構造体を作成しないといけないので、前者の方が望ましいように思います。

    プロパティはやはり、コンパイラでインライン化されたりするのが原因で、こういうのは無理なのでしょうか?
    アクセス可能なデータメンバはなるべくプロパティを使うべきだと理解しているのですが、よい方法はあるでしょうか?

    よろしくお願いします。



    2011年5月26日 3:16

回答

  • >型が次に挙げるすべての特性を持たない場合、構造体は定義しません。

    • プリミティブ型 (整数、倍精度浮動小数点数など) に似た単一の値を論理的に表す。

     

    Structの中にStructを入れるのは、値型だからいいだろうというような勘違いをしていました。

    単一の値だから階層ができることはないというのがルールなのですね。

     

    設計を見直してみることにします。ありがとうございました。

    • 回答としてマーク めめ 2011年5月26日 9:27
    2011年5月26日 9:19

すべての返信

    • isAlt が private なので、アクセスできない
    • isAlt が public だとして、値型はコピーなので書き換える意味がない

    後者については、

    keys.modifierKey.isAlt = true;
    
    という内容は、
    
    var modKey = keys.modifierKey;
    modKey.isAlt = true;
    
    という意味です。この時、modKey は keys.modifierKey のコピー(違うインスタンス)を指しているため、true に<br/>設定された modKey は即座に破棄されて、keys.modifierKey に対しては何も変更されません。
    
    期待されている操作は、
    
    var modKey = keys.modifierKey;
    modKey.isAlt = true;
    keys.modifierKey = modKey;
    
    になると思います。値型を変更するにはこのような手順を踏みます。
    
    
    2011年5月26日 3:46
  • K.Takaokaさん、返信ありがとうございます。

     

    なるほど、プロパティが書きなおしてくれるコードを示して頂いたということでしょうか?

    これは、プロパティのプロパティのプロパティみたいに階層が深くなると、値の変更がかなり面倒になる気がします。

    また、一時変数を用意してあげないと値を設定することができないのは、一時変数を用意する分だけ処理を損するような気もします。(殆どの場合は、分からない程度だと思いますが)

     

    この辺りを気にするなら、クラスに変更にして参照型にしてしまうのがよい解法となるのでしょうか?

    それとも、書くコードが1行でなくなるだけで、気にしなくてよい問題なのでしょうか?

     

    2011年5月26日 7:42
  • > この辺りを気にするなら、クラスに変更にして参照型にしてしまうのがよい解法となるのでしょうか?

    構造体とクラス、状況によりどちらを選択すべきかについてはガイドラインで謳っています。

    クラスまたは構造体の選択
    http://msdn.microsoft.com/ja-jp/library/ms229017.aspx

    構造体のデザイン
    http://msdn.microsoft.com/ja-jp/library/ms229031.aspx

    私なら、単純な値型以外をメンバに持つなら迷わずクラスにしています。


    ひらぽん http://d.hatena.ne.jp/hilapon/
    2011年5月26日 8:11
    モデレータ
  • すでに書かれているところに、十分なことが書いてあると思いますが、複製されることによる作用を避けたいならば設計を見直すべきかと思います。

    見直す方針としては、

    ○ 参照型にする

    既に使用されている既存のクラスだとインパクトが非常にでかいので、早いうちじゃないとかなりやばい。
    (複製されている前提で実装されたコードはすべて Clone() の呼び出しなどを追加しないとならないため)

    ○ プロパティをやめてメソッドにする

    プロパティによる暗黙的な set/get の呼び出しと比較して、文法的な違いから複製を書き換えるという間違いを犯さなくなります。

    ○ 公開するプロパティの粒度をかえる

    InfoKey クラスに public bool IsAlt { get { return this.modifer.isAlt; } set { this.modifler.isAlt = value; } } を作成するかんじです。

     あたりがすぐに思いつきます。

    個人的には、スキル等の異なる複数人での開発では、値型はトラブルの原因にしかならないので、ユーザコードでは完全に使わないという方針でやってます。(ただし、enumは除く)

    2011年5月26日 8:36
  • >型が次に挙げるすべての特性を持たない場合、構造体は定義しません。

    • プリミティブ型 (整数、倍精度浮動小数点数など) に似た単一の値を論理的に表す。

     

    Structの中にStructを入れるのは、値型だからいいだろうというような勘違いをしていました。

    単一の値だから階層ができることはないというのがルールなのですね。

     

    設計を見直してみることにします。ありがとうございました。

    • 回答としてマーク めめ 2011年5月26日 9:27
    2011年5月26日 9:19