Override abstract readonly property to read/write property

前端 未结 5 1299
死守一世寂寞
死守一世寂寞 2020-12-10 11:14

I would like to only force the implementation of a C# getter on a given property from a base abstract class. Derived classes might, if they want, also provide a setter for t

相关标签:
5条回答
  • 2020-12-10 11:29

    Would this suit your needs?

    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; }
        }
    }
    

    The virtual was removed, but the base value is still the only storage for the value. So this should show '5'. And the compiler should fuss about 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

    0 讨论(0)
  • 2020-12-10 11:38

    You can't do it directly, since you can't new and override with the same signature on the same type; there are two options - if you control the base class, add a second property:

    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; }
        }
    }
    

    Else you can introduce an extra level in the class hierarchy:

    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 讨论(0)
  • 2020-12-10 11:41

    I had a similar requirement where I needed an interface to be able to share common sorting functionality between two loosely related classes. One of them had a read-only Order property and the other had a read-write Order property, but I needed a way to read the property the same way from both classes.

    It turns out that this can be done by hiding the read-only value in a derived interface. Here is how I did it.

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-10 11:42

    You may do this with a constructor as following;

    public abstract class Base
    {
        public abstract int Property { get; }
    }
    
    
    public class Derived : Base
    {
        public Derived(string Property) : base(Property)
        {
    
        }
    }
    
    0 讨论(0)
  • 2020-12-10 11:48

    What about something like:

    public abstract class Base
    {
        public virtual int Property
        {
            get { return this.GetProperty(); }
            set { }
        }
    
        protected abstract int GetProperty();
    }
    
    0 讨论(0)
提交回复
热议问题