2010-10-15 87 views
6

對於這裏的鐵桿C#程序員,這似乎是一個完全愚蠢的問題 - 但是,我對面的在AWS SDK論壇示例代碼片段來了,通過它完全sideswiped:C#語法糖 - 設置對象屬性的新方法?

RunInstancesRequest runInstance = new RunInstancesRequest() 
    .WithMinCount(1) 
    .WithMaxCount(1) 
    .WithImageId(GetXMLElement("ami")) 
    .WithInstanceType("t1.micro"); 

這是非常讓人想起舊的VB6 With ... End With語法,我長期以來感嘆C#中的缺失 - 我將它編譯在我的VS2008項目中,它工作的很好,保存了許多獨立的行,分別引用這些屬性。

我敢肯定,我讀過過去解釋爲什麼VB6風格With - 塊是不是在C#,所以我的問題是文章:有這句法總是在語言的存在,或者是它最近.NET的變化已經啓用了它?我們可以將所有對象實例化,然後在同一個糖中進行屬性更改嗎?

+2

嗯,當然,你可以實現所有這些方法如果你想。但爲什麼不使用對象初始化語法? – 2010-10-15 14:14:44

+1

這裏有很好的答案,但我只能接受一個 - 所以現在它是一個專門提到* Fluent Interfacing *的人,因爲文章中的示例非常清楚發生了什麼。我感到有些尷尬,我自己並沒有建立直觀的聯繫,發現整條線的形式爲'A.B.C.D',但我從未見過這種技術。弓的另一個字符串! :) – 2010-10-15 14:34:02

回答

16

他們實施所有這些方法,每個方法也將返回RunInstancesRequest對象(又名,this)。它被稱爲Fluent Interface

+0

尼斯鏈接。我喜歡這個例子:http://en.wikipedia.org/wiki/Fluent_interface#C.23 – 2010-10-15 14:46:06

4

這不是句法糖。這些方法只是設置一個屬性並返回this對象。

0

這句法一直存在

25

無論如何這不是更好嗎?

RunInstancesRequest runInstance = new RunInstancesRequest 
{ 
    MinCount = 1, 
    MaxCount = 1, 
    ImageId = GetXMLEleemnt("ami"), 
    InstanceType = "t1.micro" 
}; 
+1

+1我喜歡學習新東西。 – Brad 2010-10-15 14:28:16

+0

我同意,爲設置屬性/構造函數,這是一個更好的語法。但是在使用現有項目的情況下,通常會修改多個屬性,或者在鏈中調用多個方法,流暢的界面會發光。這是jQuery非常好的合作原因之一。 – CaffGeek 2010-10-15 14:41:16

+1

而你不能在一個不可變的對象上使用它。就我個人而言,我認爲只有在原始對象沒有被修改的情況下才能使用這個語法(就像在Linq中一樣)。 – CodesInChaos 2010-10-15 15:14:34

1

此語法適用於RunInstancesRequest的原因是您正在進行的每個方法調用都會返回原始實例。出於同樣的原因,同樣的概念可以應用於StringBuilder,但並不是所有的類都有以這種方式實現的方法。

3

我認爲這種技術不同於VB中的With ...語法。我認爲這是一個鏈接的例子。每個方法都會返回一個自己的實例,以便您可以鏈接方法調用。

Method-Chaining in C#

+0

+1排名較高的答案沒有提到鏈接。 – 2010-11-02 14:36:50

1

我寧願有一個構造函數所有這些屬性值作爲參數,並將它們設置在類中。

+0

+1。我不喜歡讓部分構建的類生活的任何事情。我只是將它用於LINQ2SQL或其他ORM,作爲OO-ORM阻抗的人工製品,但大多數時候沒有理由。這並不意味着它不能用於正確的構造函數和類不變式,但我可以看到這將如何鼓勵脫離這一點。 – 2010-10-15 17:02:35

4
RunInstancesRequest runInstance = new RunInstancesRequest() 
.WithMinCount(1) 
.WithMaxCount(1) 
.WithImageId(GetXMLElement("ami")) 
.WithInstanceType("t1.micro"); 

==

RunInstancesRequest runInstance = new RunInstancesRequest().WithMinCount(1).WithMaxCount(1).WithImageId(GetXMLElement("ami")).WithInstanceType("t1.micro"); 

如果這是考慮語法糖,或者只是純粹的格式,我不知道。

+0

+1:'.'周圍的空白是(並且總是)被編譯器完全忽略。 – 2010-10-15 15:06:46

1

它總是在C#中存在,而且確實是在任何C風格的面嚮對象語言(呃,最流行的除了C本身C風格的語言!)

這是不公平的它比較VB6的With...End With語法,因爲它是多更清楚的是在這種情況下發生了什麼(關於VB6的With...End With唯一的好處是至少它不像JavaScript那樣糟糕,因爲它需要先前的點)。

正如人們所說的,「流暢接口」和.運算符允許前後有空白的事實相結合,因此我們可以將每個項目放在換行符中。

StringBuilder是C#中的最常見的情況下,如:

new StringBuilder("This") 
    .Append(' ') 
    .Append("will") 
    .Append(' ') 
    .Append("work") 
    .Append('.'); 

一個相關,但不完全一樣的,圖案是你鏈,其返回的不同對象的不可變對象的方法相同類型中:

DateTime yearAndADay = DateTime.UtcNow.AddYears(1).AddDays(1); 

又一正在返回從LINQ相關的方法改性IEnumerable<T>IQueryable<T>對象。

這些雖然返回不同的對象不同,而不是修改一個可變的對象,並返回相同的對象。

C++和Java比C#更常見的一個主要原因是C#具有屬性。這使得分配不同屬性的最習慣的方法可以調用相關的設置器,這在語法上與設置字段相同。但它阻止了流利的界面習慣用法的大部分常見用法。

個人,因爲流暢的界面成語不能保證(還有什麼可說的MyClass.setProp(32)應該返回this或事實上,它不應該返回32這也將在某些情況下是有用的),由於它並不像成語在C#中,我寧可不去,除了與StringBuilder,這是它幾乎存在,如C#中的一個單獨StringBuilder成語