2009-10-14 78 views
10

爲什麼ReSharper在下面的示例中爲'設置'建議readonly字段?爲什麼resharper建議只讀字段

如果我理解正確,如果您僅在構造函數中更改此字段,則應該使用readonly修飾符,但在我的示例中,我也在同一個類中的另一個方法中更改它。

我錯過了什麼?

public partial class OptionsForm : Form 
{ 
    private Settings settings; 

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

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

好的,以及如何禁用?我找不到選項... – andrecarlucci 2010-08-11 13:57:33

回答

24

當引用類型聲明爲只讀時,指針是不可變的,但不是它指向的對象。這意味着:

  • 引用類型的數據成員可以以點帶面一類的 實例進行初始化,但是一旦做到這一點是不可能的,使其 點的另一個實例在構造函數外的類
  • readonly修飾符對只讀數據成員 指向的對象沒有影響。

仔細閱讀本

Mark a C# class data member as readonly when it’s read only

+1

這是如何回答這個問題的:「爲什麼ReSharper在下面的示例中爲'設置'建議readonly字段?」 ? – zvolkov 2012-03-02 16:10:44

+0

上述回覆中提到的鏈接不起作用。我認爲這是移動到http://www.developer-corner.com/2009/01/mark-c-class-data-member-as-readonly.html – Raghav 2012-07-31 18:53:13

+0

我同意@zvolkov。它是否在鏈接中解釋?如果是這樣,請在這裏解釋鏈接。 – jcollum 2012-08-27 23:13:42

0

您不更改構造函數以外的設置,該對象與SaveData中的對象相同。對象屬性可能正在改變,但不是對象引用,所以從Resharper角度來看似乎是有意義的。

0

SaveData()方法不會更改設置變量,它會更改其屬性。設置的內容(它指的是)只在構造函數中設置。

4

一個詳細的文章記住編碼標準和設計模式的主要原因是爲了做出更容易爲人們所理解你的代碼。

通過標記字段爲「只讀」你 告訴類 他們不需要考慮 的字段的值是如何被改變的讀者。

但是,只讀字段指向的對象可以使其狀態發生更改,因此將字段標記爲只讀可能會引起誤解。因此,想一想天氣有助於讀者(例如某人)的代碼瞭解您的設計與否。

如果字段指向的對象中的值在對象生存期內發生更改,那麼我認爲字段不應該標記爲只讀。 (例如,指向的對象應該表現得好像它在你的類上的承包商被調用時是不可變的)

(但是也有一些例外,例如,使用只讀字段指向記錄器甚至認爲記錄器確實會改變日誌文件的狀態。)

+0

所以你建議在我的例子中'readonly'修飾符會讓讀者感到困惑? – sventevit 2009-10-15 07:07:50

+0

@simon,是的,隨着設置中的值發生變化,我不會將其標記爲只讀。 – 2009-10-15 08:24:51

+0

我不認爲這是一個很好的解釋。 readonly修飾符使得引用不可變,它具有特定的用途;你的blockquote說的是不對的。另外,爲什麼你決定記錄器是一個可接受的特例? – nicodemus13 2011-04-11 14:19:06

0

其實,你是對的,Resharper是錯誤的。只有在整個字段不可變的情況下,該字段才應該標記爲只讀。在你的例子中,如果你只是只讀,並啓用微軟的代碼分析,它會警告你,設置有可變屬性。

+0

不正確。我建議你看看http://msdn.microsoft.com/en-us/library/acdd6hb7%28VS.71%29.aspx – blowdart 2009-10-15 09:09:28

+0

Blowdart,你的MSDN鏈接定義了關鍵字/編譯器的行爲,而沒有進入具體的值類型vs.參考類型,也不考慮關鍵字的語義。現在,關鍵字對於值類型(以及不可變引用類型)來說工作得非常好,但對於可變引用類型有着有趣的含義。假設該字段是散列表。將該字段標記爲只讀,使得hashtable不可變?沒有!你不能改變指針指向另一個散列表,但你仍然可以改變數據。這就是爲什麼你不應該在可變引用類型上使用它。 – zvolkov 2010-08-26 20:29:50

0

這似乎有點奇怪,我無法想象Eric Lippert等人並沒有考慮這樣一個顯而易見的事實,即使參考不可變並不會使參考實例指向不可變的實例,儘管前面提到代碼分析規則確實支持上述視圖(http://msdn.microsoft.com/zh-cn/library/ms182302(v=VS.100).aspx)。

它仍然沒有任何意義。如果可變實例不應該是隻讀的,那麼,在我看來,它應該是編譯時錯誤,否則看起來是毫無意義的。

我可以看到使用引用不可變的引用,而不是它指向的實例。

1

ReSharper的建議作出的「設置」只讀:

readonly private Settings settings; 

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

,因爲在代碼掃描它的結論是,你的「設置」字段只發生在構造此相同的類。

如果你希望在這個類中提供一個部分類或者其他一些修改了「設置」的代碼,它不會再提示它是隻讀的。

一旦打上只讀編譯器就會爲警告領域的各種誤用,如:

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

這是你得到同樣的錯誤,當您試圖分配一個值恆定。

也使用參考參數修飾符是有限的。

通過遵循ReSharpers建議,如果您嘗試濫用您在初始化後確實不想更改的字段,編譯器會警告您。