2009-09-28 123 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; 
    } 
}