2014-09-11 49 views
5

很多時候我碰到需要小的不可變數據結構。在其他情況下,其他人可能會在這些情況下使用元組,但我真的不喜歡元組不會很好地閱讀並且不表達那麼多的意義。 intValue2不告訴我任何東西。在C中編寫不可變結構的最短路徑#

一個例子是爲兩個屬性的組合創建查找表(詞典),即NameRating

,使這些情況,我知道的不可變結構的最短路徑是這樣的:

public struct Key 
{ 
    public string Name { get; private set; } 
    public int  Rating { get; private set; } 

    public LolCat(string name, int rating) : this() 
    { 
     Name = name; 
     Rating = rating; 
    } 
} 

// useage 
var key = new Key("MonorailCat", 5); 

在我看來還有在這裏有很多「句法脂肪」,我想擺脫。 當我直接暴露字段時,我可以使它更具可讀性。

public struct Key 
{ 
    public string Name; 
    public int  Rating; 
} 

// useage 
var key = new Key { Name = "MonorailCat", Rating = 5 }; 

我真的很喜歡這樣的語法,因爲幾乎沒有任何語法上的脂肪。當然,最大的缺點是它不是一成不變的,所有這些都是危險的。

在理想情況下,我只是想爲這個特殊的類型,與定義的實際最低限度,如:

public immutable struct Key 
{ 
    string Name; 
    int  Rating; 
} 

// useage (needs compiler magic) 
var key = new Key(Name: "MonorailCat", Rating: 5); 

問題

是否有現實世界的解決方案一些更接近底部的例子,減少一個非常簡單的不可變結構的語法脂肪量?

+0

爲什麼在這種情況下不使用類? – Kao 2014-09-11 12:21:52

+0

爲什麼不將屬性暴露爲'readonly'字段?你至少會刪除'{get;私人設置;}'(你仍然需要構造函數)。 – casperOne 2014-09-11 12:23:45

回答

13

由於C#6,你可以寫相當緊湊struct初始化:

public struct Key 
{ 
    public string Name { get; } 
    public int Rating { get; } 

    public Key(string name, int rating) 
    { 
     this.Name = name; 
     this.Rating = rating; 
    } 
} 

...這是至少顯著短。我強烈建議實施IEquatable<Key>,請介意。

注意,當你正在處理一個結構,你仍然可以寫:

Key key = new Key(); 
Console.WriteLine(key.Rating); // 0 

...這可能不是一個問題,但一般需要至少考慮

C#6之前,其實我去甚至更長的時間比你目前的代碼,爲了寫屬性爲只讀屬性:

public struct Key 
{ 
    private readonly string name; 
    private readonly int rating; 

    public string Name { get { return name; } } 
    public int Rating { get { return rating; } } 

    public Key(string name, int rating) 
    { 
     this.name = name; 
     this.rating = rating; 
    } 
} 

我感覺這使得它更清楚地「意思是不可變的「 - 如果你有一個可寫的屬性,即使這個setter只是私人的,那也不能表達IMO的正確印象。 (雖然值得注意的是,在結構中的不變性始終是的小小位的假裝,因爲你可以在成員中分配到this ......)

+0

爲什麼仍然使用屬性,而不是直接暴露像X.L中的只讀字段。螞蟻的例子?只是爲了'意思'? – 2014-09-11 12:29:53

+0

啊沒關係。閱讀他的回答下的評論。 – 2014-09-11 12:30:43

+0

@DirkBoer:我非常*從不*暴露領域。它感覺各種各樣的錯誤:) – 2014-09-11 12:30:54

2

AFAIK,你可以是隻讀的使用,這幾乎是比使用性能的結構較短寫的最短:

public struct Key 
{ 
    public readonly string Name; 
    public readonly int  Rating; 

    public Key(string name, int rating){ 
     Name = name; 
     Rating = rating; 
    } 
} 

var key = new Key("MonorailCat", 5); 
+1

儘管這樣做有效,但確實意味着暴露*字段*而不是屬性 - 我總是謹慎。特別是,從此變爲C#6基於屬性的版本是一個突破性變化。 – 2014-09-11 12:27:11

+0

@JonSkeet我同意你的看法,但我不知道任何暴露只讀字段都可能導致問題的情況(除了你提到的破壞性更改)。有沒有我應該知道的情況? – 2014-09-11 12:30:27

+0

根據實現情況,通常不會爲字段設置UI綁定 - 並且在屬性和字段之間的差別非常微小的語言中有各種各樣的地方。當字段是隻讀的時候,它並不是很差*,但我仍然總是喜歡使用屬性。在我看來,屬性是類型和客戶之間的API的一部分;字段是一個實現細節。 (例如在野田時代,我最近大量地重新實現了一切 - 領域已經完全改變,但屬性與以前一樣...) – 2014-09-11 12:33:03

1

在C#7.2還有一個只讀結構。

readonly public struct ReadonlyPoint3D 
{ 
    public ReadonlyPoint3D(double x, double y, double z) 
    { 
     this.X = x; 
     this.Y = y; 
     this.Z = z; 
    } 
    //setters would not compile 
    public double X { get; } 
    public double Y { get; } 
    public double Z { get; } 

    private static ReadonlyPoint3D origin = new ReadonlyPoint3D(); 
    public static ref readonly ReadonlyPoint3D Origin => ref origin; 
    public ReadonlyPoint3D Scale(double factor) 
    { 
     /* all fail compilation 
     X *= factor; 
     Y *= factor; 
     Z *= factor; 
     */ 
     return new ReadonlyPoint3D(X * factor, Y * factor, Z * factor); 
    } 
} 

編譯器強制所有成員都是隻讀的。 這是作爲'in'引用而不是通常更高效的接收者副本傳遞的。

Reference

+0

+1,但我會說「哪個通常更有效率」。有幾次,當它不是如此。一般來說,大多數情況下你會很高興它在大多數情況下會更有效率,但是如果試圖優化熱點使用內部只讀結構的熱點,那麼值得分析的東西之一就是隻讀取它。 – 2017-11-21 09:42:15

+0

謝謝。同意。改變。 – acarlon 2017-11-21 10:01:03