Frage

Ich möchte nur auf die Implementierung eines C # Getter zwingen, auf eine bestimmte Eigenschaft von einer Basis abstrakte Klasse. Abgeleitete Klassen können, wenn sie wollen, bieten auch einen Setter für diese Eigenschaft für die öffentliche Nutzung des statisch gebundenen Typ.

In Anbetracht der folgende abstrakte Klasse:

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

Wenn ich eine abgeleitete Klasse will, die auch einen Setter implementiert, konnte ich naiv versuchen:

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

    private int field;
}

Aber dann bekomme ich einen Syntaxfehler, da ich versuche, die nicht vorhandenen Setter außer Kraft zu setzen. Ich habe versucht, eine andere Art und Weise, wie erklären die Basis Setter private und so und ich stolpere immer noch auf alle Arten von Fehlern mich zu verhindern, das zu tun. Es muss ein Weg, das zu tun, wie es bricht keine Basisklasse Vertrag.

Incidentaly, kann es mit Schnittstellen erfolgen, aber ich brauche wirklich, dass Default-Implementierung.

stolperte ich in dieser Situation so oft, ich frage mich, ob es eine versteckte C # Syntax Trick, das zu tun war, sonst werde ich nur mit ihr leben und eine manuelle SetProperty () -Methode implementieren.

War es hilfreich?

Lösung

Sie können es nicht direkt tun, da Sie nicht mit der gleichen Unterschrift auf dem gleichen Typ new und override können; gibt es zwei Möglichkeiten - wenn Sie die Basisklasse zu steuern, fügen Sie ein zweiten Eigenschaft:

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 können Sie eine zusätzliche Ebene in der Klassenhierarchie vorstellen:

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

Andere Tipps

Was ist so etwas wie:

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

    protected abstract int GetProperty();
}

Würde das Ihre Bedürfnisse?

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

wurde Der virtual entfernt, aber der Grundwert ist immer noch der einzige Speicher für den Wert. So soll dies zeigen ‚5‘. Und der Compiler sollte über b.Value = 4; Aufheben

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

-Jesse

hatte ich eine ähnliche Anforderung, wo ich eine Schnittstelle benötigt, um gemeinsame Sortierfunktionalität zwischen zwei losen verwandten Klassen zu teilen. Einer von ihnen hatte eine Nur-Lese-Order-Eigenschaft und die andere eine Schreib-Lese-Order-Eigenschaft hatten, aber ich brauchte eine Möglichkeit, die Eigenschaft, auf die gleiche Weise aus beiden Klassen zu lesen.

Es stellt sich heraus, dass dies durch Ausblenden des Nur-Lese-Wertes in einer abgeleiteten Schnittstelle durchgeführt werden kann. Hier ist, wie ich es tat.

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;
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top