27

我只想强制在基础抽象类的给定属性上实现 C# getter。如果需要,派生类还可以为该属性提供一个设置器,以供公众使用静态绑定类型。

给定以下抽象类:

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

如果我想要一个也实现 setter 的派生类,我可以天真地尝试:

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

    private int field;
}

但是后来我得到一个语法错误,因为我尝试覆盖不存在的设置器。我尝试了其他一些方法,例如将 base setter 声明为私有等,但我仍然偶然发现各种错误阻止我这样做。必须有一种方法可以做到这一点,因为它不会破坏任何基类合同。

顺便说一句,它可以用接口来完成,但我真的需要那个默认实现。

我经常偶然发现这种情况,我想知道是否有隐藏的 C# 语法技巧可以做到这一点,否则我将忍受它并实现手动 SetProperty() 方法。

4

5 回答 5

18

您不能直接执行此操作,因为您不能在同一类型上使用相同的签名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; }
    }
}
于 2009-09-28T21:09:07.050 回答
6

这会满足您的需求吗?

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;

-杰西

于 2013-10-22T18:26:54.470 回答
3

怎么样的东西:

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

    protected abstract int GetProperty();
}
于 2009-09-28T21:09:24.927 回答
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;
    }
}
于 2013-12-07T13:24:15.433 回答
-1

您可以使用以下构造函数执行此操作;

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


public class Derived : Base
{
    public Derived(string Property) : base(Property)
    {

    }
}
于 2020-03-13T14:04:38.503 回答