2009-09-28 154 views
19

我想只強制執行基本抽象類的給定屬性上的C#getter。派生類可以,如果他們想要的話,也可以爲該屬性提供一個setter用於靜態綁定類型的公共使用。重寫抽象只讀屬性以讀取/寫入屬性

鑑於以下抽象類:

public abstract class Base 
{ 
    public abstract int Property { get; } 
} 

如果我想要一個派生類還實現了一個二傳手,我天真地嘗試:

public class Derived : Base 
{ 
    public override int Property 
    { 
     get { return field; } 
     set { field = value; } // Error : Nothing to override. 
    } 

    private int field; 
} 

但後來我得到一個語法錯誤,因爲我嘗試覆蓋不存在的setter。我嘗試了一些其他方式,比如聲明基本setter是私人的,而且我仍然偶然發現了阻止我這樣做的所有錯誤。必須有辦法做到這一點,因爲它不會破壞任何基礎合同。另外,它可以通過接口完成,但我真的需要這個默認實現。我想知道是否有一個隱藏的C#語法技巧來做到這一點,否則我只會忍受它並實現手動SetProperty()方法。

+0

交叉鏈接:http://stackoverflow.com/questions/2243886/make-a-read-only-property-writable-in-the-derived-class – Mikhail 2011-04-06 10:47:49

回答

11

你不能直接這樣做,因爲你不能在相同的類型上使用相同的簽名newoverride;有兩種選擇 - 如果你控制的基類,添加屬性:

public abstract class Base 
{ 
    public int Property { get { return PropertyImpl; } } 
    protected abstract int PropertyImpl {get;} 
} 
public class Derived : Base 
{ 
    public new int Property {get;set;} 
    protected override int PropertyImpl 
    { 
     get { return Property; } 
    } 
} 

否則,您能介紹的類層次結構的額外級別:

public abstract class Base 
{ 
    public abstract int Property { get; } 
} 
public abstract class SecondBase : Base 
{ 
    public sealed override int Property 
    { 
     get { return PropertyImpl; } 
    } 
    protected abstract int PropertyImpl { get; } 
} 
public class Derived : SecondBase 
{ 
    public new int Property { get; set; } 

    protected override int PropertyImpl 
    { 
     get { return Property; } 
    } 
} 
+0

您的解決方案很有意思,我會思考有一點點在他們身上。 – Coincoin 2009-09-28 21:39:22

+1

你的解決方案是最接近事物的東西。但我認爲不強迫派生類去做雜技是可能的。 – Coincoin 2009-09-29 14:42:16

2

什麼是這樣的:

public abstract class Base 
{ 
    public virtual int Property 
    { 
     get { return this.GetProperty(); } 
     set { } 
    } 

    protected abstract int GetProperty(); 
} 
+1

任何繼承者現在必須重寫他們兩個 - 有點多餘? – 2009-09-28 21:24:35

+0

僅限於覆蓋該屬性。否則,沒有虛擬財產,實際上可能是一個可以接受的選擇。 – Coincoin 2009-09-28 21:34:28

+1

如果你不覆蓋屬性,這個集合的目的是非常不尋常的。 – 2009-09-28 21:38:57

1

這是否適合您的需求?

public abstract class TheBase 
{ 
    public int Value 
    { 
     get; 
     protected set; 
    } 
} 
public class TheDerived : TheBase 
{ 
    public new int Value 
    { 
     get { return base.Value; } 
     set { base.Value = value; } 
    } 
} 

virtual除去,但是基準值仍然爲值的唯一存儲設備。所以這應該顯示'5'。而編譯器應該計較b.Value = 4;

TheDerived d = new TheDerived(); 
d.Value = 5; 
TheBase b = d; 
//b.Value = 4; // uncomment for compiler error 
cout << "b.Value == " << b.Value << endl; 

-Jesse

1

我有地方,我需要的接口,以便能夠在兩個鬆散的相關類之間有着共同的排序功能類似的要求。其中一個具有隻讀Order屬性,另一個具有讀寫Order屬性,但我需要一種以同樣方式從兩個類讀取屬性的方法。

事實證明,這可以通過在派生接口中隱藏只讀值來完成。這是我如何做到的。

interface ISortable 
{ 
    int Order { get; } 
} 

interface ISortableClass2 
    : ISortable 
{ 
    // This hides the read-only member of ISortable but still satisfies the contract 
    new int Order { get; set; } 
} 

class SortableClass1 
    : ISortable 
{ 
    private readonly int order; 

    public SortableClass1(int order) 
    { 
     this.order = order; 
    } 

    #region ISortable Members 

    public int Order 
    { 
     get { return this.order; } 
    } 

    #endregion 
} 

class SortableClass2 
    : ISortableClass2 
{ 
    #region ISortableClass2 Members 

     public int Order { get; set; } 

    #endregion 
} 

class RunSorting 
{ 
    public static void Run() 
    { 
     // Test SortableClass1 
     var list1 = new List<SortableClass1>(); 

     list1.Add(new SortableClass1(6)); 
     list1.Add(new SortableClass1(1)); 
     list1.Add(new SortableClass1(5)); 
     list1.Add(new SortableClass1(2)); 
     list1.Add(new SortableClass1(4)); 
     list1.Add(new SortableClass1(3)); 

     var sorted1 = SortObjects(list1); 

     foreach (var item in sorted1) 
     { 
      Console.WriteLine("SortableClass1 order " + item.Order); 
     } 

     // Test SortableClass2 
     var list2 = new List<SortableClass2>(); 

     list2.Add(new SortableClass2() { Order = 6 }); 
     list2.Add(new SortableClass2() { Order = 2 }); 
     list2.Add(new SortableClass2() { Order = 5 }); 
     list2.Add(new SortableClass2() { Order = 1 }); 
     list2.Add(new SortableClass2() { Order = 4 }); 
     list2.Add(new SortableClass2() { Order = 3 }); 

     var sorted2 = SortObjects(list2); 

     foreach (var item in sorted2) 
     { 
      Console.WriteLine("SortableClass2 order " + item.Order); 
     } 
    } 

    private static IEnumerable<T> SortObjects<T>(IList<T> objectsToSort) where T : ISortable 
    { 
     if (objectsToSort.Any(x => x.Order != 0)) 
     { 
      return objectsToSort.OrderBy(x => x.Order); 
     } 

     return objectsToSort; 
    } 
}