2016-05-12 71 views
0

更新1
看起來好像我的英語非常糟糕,或者人們只是不給一個...瞭解我在問什麼,或者只是看看帖子的標題。爲什麼不顯式初始化只讀自動實現屬性在c#6中有效?

C#5 specification明確規定:

Because the backing field is inaccessible, it can be read and written only through the property accessors, even within the containing type. This means that automatically implemented read-only or write-only properties do not make sense, and are disallowed.

public string MyProperty {get;}有沒有意義,但它的成本沒有爲編譯器產生的吸氣甚至沒有交戰約缺少二傳手。備份字段將使用默認值進行初始化。這是什麼意思?這意味着設計人員花費了一些努力來實施驗證,以引入可以省略的功能。

現在考慮C#6:

在C#6自動實現屬性的初始化是introduced

public string FirstName { get; set; } = "Jane"; 


public string FirstName { get; } = "Jane"; 

在後一種情況下,屬性可以在構造函數中設置,以及:

public class Program 
{ 
    public string ImagePath { get; } 

    public static void Main() 
    {  
    } 

    public Program() 
    { 
     ImagePath = ""; 
    }  
} 

但只有在被宣佈屬性的類的構造函數。派生類不能設置屬性的值。

現在問自己這是什麼性質意味着,如果它不是在構造函數初始化:

property string My {get;} 

這相當於C#5禁止財產的100%。它沒有任何意義。
但是在C#5中無效的聲明在C#6中變得有效。但是語義完全沒有改變:這個屬性在沒有顯式初始化的情況下是無用的。

這就是爲什麼我問:

爲什麼沒有初始化只讀自動實現的屬性是在C#6有效嗎?

我希望看到作爲一個答案是什麼:

    我最初設想
  • 無論揭穿約在C#中的變化6
  • 或解釋如何以及爲什麼編譯器設計人員改變他們的想法 什麼有道理,什麼都沒有。

我發現答案0​​是完全不相關的。這只是一個事實。我尋找原因。我不相信編譯器設計者只是拋硬幣就決定編譯器行爲的改變。

這是一個很好的答案example

原來的問題

VS2015該代碼被編譯沒有錯誤:

public class Program 
{ 
    public string ImagePath { get; } 

    public static void Main() 
    { 
     Console.WriteLine("Hello World"); 
    } 
} 

然而,在VS2013我得到錯誤:

Compilation error (line 5, col 28): 'Program.ImagePath.get' must declare a body because it is not marked abstract or extern. Automatically implemented properties must define both get and set accessors.

我知道關於initiali zable自動實現的屬性,並在VS2015字段獲取默認值,即null這裏。但是,有趣的是,要知道爲什麼此片段在C#5中無效?

Initializable自動實現readonly財產留給沒有明確的初始化我看來有點奇怪。這可能是一個錯誤,而不是意圖。我個人比較喜歡的編譯器需要顯式初始化在這種情況下:

public string ImagePath { get; } = default(string);

好吧,我知道這樣的屬性也被分配在構造函數:

public class Program 
{ 
    public string ImagePath { get; } 

    public static void Main() 
    {  
    } 

    public Program() 
    { 
     ImagePath = ""; 
     DoIt(); 
    } 

    public void DoIt() 
    { 
     //ImagePath = "do it"; 
    }  
} 

public class My : Program 
{ 
    public My() 
    { 
     //ImagePath = "asdasd"; 
    } 
} 

但是,如果編譯器檢查局部變量未初始化,屬性也可能相同。

那麼,爲什麼是它,因爲它是什麼?

+2

爲什麼不問問編譯器爲什麼允許非初始化只讀字段?情況完全一樣。 – Evk

+0

@Evk如果這種行爲改變了,我會問。 –

+0

只讀屬性是一項新功能,因此沒有任何行爲改變。我的意思是「這可能是一個錯誤,而不是意圖,我個人更喜歡編譯器在這種情況下需要顯式初始化」 - 對於只讀字段也是如此。 – Evk

回答

5

編譯器會提醒您自動屬性必須定義兩個訪問。例如,您可以使用以下方法修復錯誤:

public string ImagePath { get; private set; } 

假設您不打算在類之外設置屬性。

至於爲什麼你已經申報了調節器或手動執行的財產 - 嗯,什麼好就可以從讀取屬性,但總是返回其類型的默認值,因爲沒有設置它的方法?相反,你可以寫信給一個物業,但它既不能讀取也不能掛鉤它的二次財產有什麼好處?

C#6.0提供了選項一次寫入,讀取多個自動屬性;這是一個巨大的差異,因爲該值可以任意選擇,使您可以方便地使用具有不可變值的屬性的語法。

+1

問題不在於爲什麼它無效C#5,而是爲什麼它已經成爲有效的C#6. – hvd

+1

添加到此之前,僅在C#6.0中才添加getter-only自動屬性,因此C#5爲什麼會大喊大叫。 [Roslyn Github](https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#getter-only-auto-properties) – AntiTcb

+0

@hvd:因爲在C#6中您可以選擇只讀屬性的值,這使得它非常有用。我添加了最後一段來明確提及這一點。 – Jon

2

我不知道爲什麼你的問題已經下來了投票。這是一個有趣的觀察,但請記住,這不是一個突破性的變化 - 它只是「剩餘」其他功能的「新功能」 - 初始化自動實現的屬性。

這意味着它以前有沒有意義的,但現在它了。

而且,我覺得它一直有感覺。例如。當你有一些基類或接口,例如

interface IPerson 
{ 
    int Age { get; } 
} 

有一天你可能要實現空對象模式,其中年齡是無關緊要的。在c#5中,您必須編寫public int Age { get { return 0; } },而在c#6中,您可以簡單地執行public int Age { get; }甚至將接口轉換爲抽象類,只將其定義從interface更改爲abstract class

+2

>我認爲它總是有道理。其實,我也是=)我們可以問爲什麼然後他們決定以這種方式在C#5中完成。我同意,我的問題主要是關於語言設計及其哲學。這就是爲什麼我喜歡Bill Wagner的[talk](https://vimeo.com/154708153)。我總是受到設計師加權前瞻性思考的啓發。很多向他們學習。 –

相關問題