13

以下の例で、ReSharperが「設定」の読み取り専用フィールドを提案しているのはなぜですか?

私が正しく理解してreadonlyいれば、コンストラクターでのみこのフィールドを変更する場合は修飾子を使用する必要がありますが、私の例では、同じクラスの別のメソッドでも変更します。

私は何が欠けていますか?

public partial class OptionsForm : Form
{
    private Settings settings;

    public OptionsForm(Settings s)
    {
        settings = s;
    }

    private void SaveData()
    {
        settings.ProjectName = TextBoxProject.Text;
    }
}
4

7 に答える 7

27

参照型が読み取り専用として宣言されている場合、ポインターは不変ですが、ポインターが指すオブジェクトは不変です。この意味は:

  • 参照型データ メンバーは、クラスのインスタンスを指すように初期化できますが、これが完了すると、コンストラクターの外部にあるクラスの別のインスタンスを指すようにすることはできません。
  • readonly 修飾子は、readonly データ メンバーが指すオブジェクトには影響しません。

これに関する詳細な記事を読む

読み取り専用の C# クラス データ メンバーを読み取り専用としてマークする

于 2009-10-14T11:57:55.210 に答える
5

標準と設計パターンをコーディングする主な理由は、人々がコードを理解しやすくすることです。

フィールドを「読み取り専用」としてマークすることで、フィールドの値がどのように変更されるかを考慮する必要がないことをクラスの読者に伝えます。

ただし、読み取り専用フィールドが指すオブジェクトは状態が変化する可能性があるため、フィールドを読み取り専用としてマークすると誤解を招く場合があります。コードの読者 (たとえば人)が設計を理解するのに役立つかどうかについて考えてみてください。

フィールドが指すオブジェクトの値がオブジェクトの有効期間内に変更された場合、フィールドを読み取り専用としてマークする必要はないと思います。(たとえば、指定されたオブジェクトは、クラスのコントラクターが呼び出されるまでに不変であるかのように動作する必要があります)

(ただし、いくつかの例外があります。たとえば、ロガーがログ ファイルの状態を変更する場合でも、読み取り専用フィールドを使用してロガーを指すことは問題ありません。)

于 2009-10-14T12:42:14.170 に答える
2

ReSharper は、「設定」を読み取り専用にすることを提案しています。

readonly private Settings settings;

public OptionsForm(Settings s)
{
    settings = s;
}

コードをスキャンすると、「設定」フィールドはこの同じクラスのコンストラクターでのみ発生すると結論付けられるためです。

ただし、「設定」を変更する部分クラスまたはこのクラスの他のコードを提供する場合、それが読み取り専用であることを示唆しなくなります。

読み取り専用としてマークされると、コンパイラは次のようなフィールドのさまざまな誤用を警告するフラグを立てます。

The left-hand side of an assignment must be an l-value

これは、定数に値を代入しようとしたときに発生するエラーと同じです。

また、refおよびoutパラメータ修飾子の使用も制限されています。

ReSharper の提案に従うことで、初期化後に本当に変更しないつもりのフィールドを誤用しようとすると、コンパイラによって警告されます。

于 2011-12-11T17:33:05.157 に答える
0

これは少し奇妙に思えます。参照を不変にしても、参照が指すインスタンスを不変にしないという明白な事実をエリック・リッパートらが考慮しなかったとは想像できませんが、前述のコード分析規則ではそうです。上記のビューをサポートします (http://msdn.microsoft.com/en-us/library/ms182302(v=VS.100).aspx)。

それはまだ本当に意味がありません。変更可能なインスタンスが読み取り専用であってはならない場合、私の見解では、それはコンパイル時のエラーである必要があり、それ以外の場合はかなり無意味に思えます。

参照が指すインスタンスではなく、参照を不変にすることの使用法を見ることができます。

于 2011-04-11T14:29:27.137 に答える
0

実際、あなたは正しく、Resharper は間違っています。フィールド全体が不変である場合にのみ、フィールドを読み取り専用としてマークする必要があります。あなたの例では、読み取り専用にしてMicrosoftのコード分析を有効にすると、設定に変更可能なプロパティがあることが警告されます。

于 2009-10-14T12:58:09.100 に答える
0

コンストラクターの外で設定を変更していません。オブジェクトは SaveData のオブジェクトと同じです。オブジェクトのプロパティは変更されている可能性がありますが、オブジェクト参照は変更されていない可能性があるため、Resharper の観点からは理にかなっているようです。

于 2009-10-14T11:51:43.040 に答える
0

SaveData() メソッドは設定変数を変更せず、そのプロパティの 1 つを変更します。設定内容(何を参照するか)はコンストラクタで設定するだけです。

于 2009-10-14T11:53:14.597 に答える