2015-04-23 69 views
1

我有一個C#基類的枚舉屬性,我想對所有派生類有效地只讀,除了一個(我需要該屬性是可讀寫的)。如何使派生類中的只讀屬性可寫?

我枚舉聲明,像這樣:

enum Visibility { Public, Shared, Private } 

(枚舉成員的名字都無關,與C#可見性修飾符,順便!)

起初,我以爲我能申報基類的屬性,像這樣:

abstract class DataViewBase 
{ 
    public Visibility Visibility { get; protected set; } 
} 

,然後更改派生類的聲明:

sealed class FooDataView : DataViewBase 
{ 
    public Visibility Visibility { get; set; } 
} 

從而使二傳手公衆開放,但我應該意識到這個隱藏基能見度財產,並生成一個編譯器警告。添加new關鍵字(即public new Visibility ...)擺脫了警告,但FooDataView上的屬性實際上成爲一個全新的屬性,與基類中的屬性沒有任何關聯。因此,如果我這樣做:

var foo = new FooDataView(); 
    foo.Visibility = Visibility.Shared; 
    Console.WriteLine(foo.Visibility); // Shared 
    var casted = (DataViewBase) foo; 
    Console.WriteLine(casted.Visibility); // Public 

兩個能見度屬性值不同,這是不是我想要的。

我最終圍繞這個工作通過聲明的屬性,像這樣:

sealed class FooDataView : DataViewBase 
{ 
    public new Visibility Visibility 
    { 
     get { return base.Visibility; } 
     set { base.Visibility = value; } 
    } 
} 

這確保了兩個能見度性能保持「同步」。

但是,在完成了所有這些後,我想知道是否有另一種方法來完成我想要的功能(根據問題標題),因爲我的解決方案似乎有些不雅。我想不出任何其他明顯的解決方案。

+0

「更改派生類的聲明」 - 在.NET中,這通常與聲明「全新」成員同義。您可以分別使用'virtual'和'override'關鍵字來更改成員的*行爲*(同時保留*界面*)。然而,在你的情況下,我會準確地建議你最終自己做了什麼,讓所有類繼承只讀屬性,並通過一個特定類中的可寫屬性來映射該屬性。你可能想要自己添加一個答案,並在一段時間後將自己的答案標記爲已接受。 –

回答

1

如何對這兩個:

1.添加新方法

class FooDataView : DataViewBase 
{ 
    public void ChangeVisibility(Visibility visibility) 
    { 
     Visibility = visibility; 
    } 
} 

只需添加一個新的ChangeVisibility()方法。我認爲這是最簡單的。

2.使用接口:

public interface IDataView 
{ 
    Visibility Visibility { get; } 
} 

public class DataView : IDataView 
{ 
    public Visibility Visibility { get; set; } 
} 

public class PrivateDataView : IDataView 
{ 
    public Visibility Visibility 
    { 
     get { return Visibility.Private; } 
    } 
} 

個人而言,我更喜歡第一種方法。

+0

第一種方法最有意義。對於這個類的用戶來說,它涉及到設置屬性和調用方法的區別,我認爲前者因其簡單性而勝出。但是,無論哪種方法都需要將其轉換爲接口,任何一種方法都更適合IMO。 –

+0

是的,我同意。我也更喜歡第一種方法。 –

+0

我已經將此標記爲接受的答案,但實際上發佈的任何答案都可以工作。我認爲你的第一個解決方案(改變可視性的方法)對於「最終用戶」來說是最容易使用的。 –

1

然而,在做這一切,我不知道是否有完成我想要的(根據問題的標題)的另一種方式 後,給出 我的解決方案似乎有點不雅。我想不出任何其他的 明顯的解決方案。

沒有其他解決方案。爲什麼你想改變屬性在派生類中公開設置(似乎setter也應該在基類中公開)?也許你應該以其他方式公開這個功能。

+0

_你爲什麼要將屬性改爲在派生類中公開設置_:基本上,我的所有派生類型都具有可見性屬性非常重要,因爲我的代碼通常處理基類。但是,只有一個派生類型應該允許「最終用戶」更改可見性;對於所有其他派生類型,可見性可能不同於基本類型(因此_protected_ setter),但在創建對象時本質上是硬編碼和設置的。 –

+0

我想我可以做的是在基類中創建一個公共虛擬getter/setter,在基類設置器中拋出異常,但重寫派生類中的getter/setter以使用其自己的專用支持字段。但是,我也在序列化這些對象,並認爲setter中的異常會在反序列化時造成麻煩。 –

1

您可以創建訪問的setter接口:在你

interface ISetVisibility { 
    Visibility Visibilty {set;} 
} 

class MyDerived : MyBase, ISetVisibility { 
    Visibility ISetVisibilty.Visibility { set {/* ... */ } } 
} 

現在主類,你可以使用以下方法:

((ISetVisibility) myDerived).Visibility = Visibilty.Shared; 
+0

這確實有用,而且非常優雅。正如你在代碼中所說明的那樣,唯一的缺點是類的用戶必須強制轉換到接口才能設置屬性值。 –

+0

此外,您可能想要編輯您的答案以刪除「公共」訪問修飾符:它們不能在接口成員上聲明,也不能在顯式實現接口成員時聲明。 –

+0

@StevenRands啊謝謝,你是對的。我已經更新了相應的答案 – HimBromBeere