Aba-Log

作ったりする人のあれこれ

CA1819で怒られたら

CA1819 : Microsoft.Performance : コレクションを返すために、またはメソッドに設定するために'SomeClass.SomeByteArrayGetOnly' を変更してください。

こういう文章を見ると、そもそも日本語で表示すること事態が問題にも思える。

CA1819が言いたいことは、 ArrayのPropertyはGetだけにしていても実際は中身を弄れちゃうから危ないよ ということ。

setがなくても中身の変更はできちゃうんですよね。

Arrayは参照型

そも、Arrayは参照型なので、やり取りされるのはメモリ上の所在。

またArrayは先頭番地を持つ事になるので、Arrayを箱でイメージすると

一つの型のサイズ分の幅と、初期化した時にセットした個数分の高さを持つ箱

の先頭番地をやり取りすることになる。

なのでPropertyをGetだけにする、という事は

  • 新しい箱の場所を指定する
  • 別の形の箱に置き換える

などができなくなるだけで、箱の中身云々の操作については制限できていない。

じゃあどうすりゃええのん

CA1819: プロパティは、配列を返すことはできません

  • MSDN的にはArrayのクローンを返す様にする
  • ReadOnlyCollectionにする

クローンを返す、の実効的なメリットがよく分からない。 ので大人しくReadOnlyCollectionにしといたら良いと思う。

なので、これを

public byte[] SomeArray{get;}

こうする

private readonly byte[] someArray;
public ReadOnlyCollection<byte> => Array.AsReadOnly(someArray);

でも、そもそもプロパティにgetだけ書くってことは弄られたくないってことなんだから

それが出来ちゃうアクセサーの仕様のがおかしくない?とも思う。

箱のサイズと場所は弄れないようにしたいけど中身はご自由にどうぞ、にしたいパターンってある?

参考

参照型(C#リファレンス)

値型(C#リファレンス)

値型と参照型の区別と違い クラスと構造体の違い

Array.AsReadOnly

C#に配列をReadOnlyにする表記法を導入してくれないだろうか…

#003 Rhino.mocsでスタブの引数のコールバックに任意の値を注入する

と、いうかStubが実行されたときに任意のArgを色々する方法

そもそも何でRhino.mocsなん、という所については少し前に書かれたテストをメンテしないといけなかったから。

target.Stub(
    s=>s.DoSomething(
        Arg1,
        Arg<Action<string>>.Is.NotNull
    ))
    .WhenCalled(
        action =>{
            var test =action.Argument[1] as Action<T>;
            test?.Invoke("注入したいもの");
        }
    )
    .Return("targetの戻り値");
)

というかRhino.mocsの情報は新しいのあんまりないと思ったらここ2014年辺りから更新されてないとか何とか…