2015-04-03 35 views
23

在Java中,我能有一個這樣的對象:我可以初始化在C#中使用不同類型的類的公共屬性嗎?

public class MyObject { 

    private Date date; 

    public Date getDate() { 
     return date; 
    } 

    public void setDate(Date date) { 
     this.date = date; 
    } 

    public void setDate(String date) { 
     this.date = parseDateString(date); 
    } 

    private Date parseDateString(String date) { 
     // do magic here 
     return dateObj; 
    } 

} 

這是很好的,因爲我有我的一個屬性的getter和setter方法多。我可以通過傳遞一個Date對象或一個String來設置「date」屬性,然後讓這個類找出它。

在C#中看起來事情有點不同。我可以這樣做:

public class MyObject 
{ 
    public DateTime Date { get; set; } 
} 

這裏的速記顯然是最優的。但是,我不確定是否有任何內置的方式來重載setter以接受多種類型。我意識到我可以創建一個單獨的公共方法來設置值,但這會犧牲使用對象初始值設定項的能力。

有沒有什麼辦法可以直接重載C#的公共屬性上的setter?或者這僅僅是一種語言限制,它不能完成?

+2

不是答案,但我會在字符串到MyClass之外的解析。無論如何,在C#中你只需要使用'DateTime.Parse'。 – 2015-04-03 19:40:11

回答

22

其他答案都是正確的......但如果你堅持,你能做到在幾個方面:

  1. 使用第二個屬性只是一個二傳手:

    public string DateText { set { Date = ParseDateString(value); } } 
    

    避免這種可能的話,它只會增加混亂:-)

  2. 使用方法代替屬性(與在Java中執行的操作相同)。方法可以重載。這應該是最推薦的方式。

  3. 使用自定義類(而不是DateTime)並提供DateTime,string和您的類之間的隱式轉換。不建議,除非你打算在其他地方使用它。

  4. 更改屬性object和二傳手提供您的轉換:請不要這樣做

+1

我會大膽強調**,如果你堅持**部分,集合屬性是我的書中的代碼味道... + 1爲完整性雖然;) – 2015-04-03 18:48:48

+0

@ Mat'sMug肯定。我已編輯添加額外的評論:-) – Jcl 2015-04-03 18:49:59

+3

當涉及到閱讀代碼時,隱式轉換非常棘手。相反,您可以使用顯式轉換。 – 2015-04-03 18:50:24

10

自動屬性不支持這一點。所以你必須像在Java中一樣做。

當然,您也可以將它們混合使用:提供一個自動屬性和額外的set-methods來設置使用不同類型的屬性。

public class MyObject 
{ 
    public DateTime Date { get; set; } 

    public void SetDate(string date) 
    { 
     this.Date = DateTime.Parse(date); 
    }  
} 
16

好吧,你正在比較蘋果和香蕉。你在這裏的Java什麼:

public void setDate(Date date) { 
    this.date = date; 
} 

public void setDate(String date) { 
    this.date = parseDateString(date); 
} 

看起來像在C#:

public void SetDate(Date date) 
{ 
    this.date = date; 
} 

public void SetDate(String date) 
{ 
    this.date = ParseDateString(date); 
} 

唯一的區別是PascalCase成員名稱和範圍,左大括號的位置。

您的Java代碼已經超載方法;上面的C#已經重載了方法。

AFAIK你不能超載屬性setter,因爲:

public DateTime Date 
{ 
    get { return this.date; } 
    set { this.date = value; } 
} 

...的value類型由成員,這裏DateTime的類型決定。

所以如果你想方法超載,過載方法,而不是性能。請記住,無論如何,C#屬性只是getter & setter方法的語法糖。

+0

我不認爲有什麼概念性的原因,爲什麼.NET不能允許屬性重載setter,如果.NET語言在看到屬性集語法時會使用與他們對方法相同的重載邏輯(與作爲第一個參數的表達式的右側類型)。在語義上,如果結果與脅迫要設置爲屬性的主類型的值不同,那麼在這種情況下,這種情況會變得不可靠,但是在多種類型可以相互轉換的情況下,直接將prop設置爲特定類型可能會比轉換然後設置。 – supercat 2015-04-03 20:48:47

+1

@supercat我認爲這是一個語言/語法約束(C#)而不是.NET範圍的東西。 VB.NET確實支持參數化的getter/setters(heck,VB6沒有!)。如果我沒有記錯,屬性會編譯爲CIL中的'get_'和'set_'方法。 – 2015-04-03 20:55:49

+0

在VB.NET和C#中,屬性解析發生在系統確定正在處理屬性之前。如果沒有,可以有一個'IReadableFoo '接口,該接口公開一個帶有getter的'Foo'屬性和'IWritableFoo ',它用setter公開'Foo',然後讓'IReadWriteFoo '簡單地繼承。但是,由於綁定完成的方式,getter和setter都不能用於'IReadWriteFoo'類型的變量;試圖說'it.Foo = 9;'或'x = it。Foo;'會被拒絕,因爲它是(假定)不明確,是否有人試圖使用...... – supercat 2015-04-03 21:00:12

10

我會寫一個不同的答案,並聲稱

public void setDate(Date date) { 
    this.date = date; 
} 

public void setDate(String date) { 
    this.date = parseDateString(date); 
} 

首先是不好的做法。

通過以上操作,您聲明字符串和日期都是Date的有效值。情況並非如此 - 你真正想要的是Date。如果用戶有一個字符串並希望它轉換爲Date,則它們應該依賴於Date API (Java中的DateFormat.parse(),C#中的DateTime.Parse()中的字符串解析功能,而不是您的API。

如果Date是由你定義一個類,你確實想Datestring是可以互換的,你應該在Date類使用implicit conversations,不要求你Date類的用戶編寫過載。

相關問題