C # Eigenschaft nicht verfügbar in abgeleiteten Klasse
-
23-09-2019 - |
Frage
Ich bin nicht sicher, was los ist. Ich habe die folgende Basisklasse:
public class MyRow : IStringIndexable, System.Collections.IEnumerable,
ICollection<KeyValuePair<string, string>>,
IEnumerable<KeyValuePair<string, string>>,
IDictionary<string, string>
{
ICollection<string> IDictionary<string, string>.Keys { }
}
Und dann habe ich diese abgeleitete Klasse:
public class MySubRow : MyRow, IXmlSerializable, ICloneable,
IComparable, IEquatable<MySubRow>
{
public bool Equals(MySubRow other)
{
// "MyRow does not contain a definition for 'Keys'"
foreach (string key in base.Keys) { }
}
}
Warum erhalte ich diesen Fehler? „‚MyNamespace.MyRow‘enthält keine Definition für‚Keys‘“. Beide Klassen sind im MyNamespace
Namespace. Ich habe versucht, Zugriff auf this.Keys
und base.Keys
und weder Werke aus MySubRow
. Ich versuchte, die Keys
Eigenschaft als public
in MyRow
Markierung bekam aber „Der Modifikator‚öffentlich‘für diesen Titel nicht gültig ist“, ich glaube, weil es notwendig ist, eine Schnittstelle zu implementieren.
Lösung
Sie sind die Umsetzung der Keys
Eigenschaft explizit. Wenn Sie möchten, dass das Mitglied öffentlich zugänglich machen (oder protected
), ändert IDictionary<string, string>.Keys
zu Keys
und fügen Sie die entsprechenden Sichtbarkeitsmodifizierer vor ihm.
public ICollection<string> Keys { ... }
oder
protected ICollection<string> Keys { ... }
Sie könnten base
als Instanz IDictionary<string, string>
Referenz auch:
((IDictionary<string, string>)base).Keys
Weitere Informationen:
(nach zu urteilen Ihre Kommentare erscheinen Sie mit dem Unterschied vertraut zu sein, aber andere können nicht sein)
C # Schnittstellen-Implementierung kann auf zwei Arten erfolgen: implizit oder explizit. Betrachten wir diese Schnittstelle:
public interface IMyInterface
{
void Foo();
}
Eine Schnittstelle ist nur ein Vertrag für das, was Mitglieder einer Klasse muss, um Code zur Verfügung stellen, die es aufruft. In diesem Fall haben wir eine Funktion namens Foo
, die keine Parameter und gibt nichts nimmt. Eine implizite Schnittstellen-Implementierung bedeutet, dass Sie ein public
Mitglied aussetzen müssen, die den Namen und die Unterschrift des Mitglieds an der Schnittstelle übereinstimmt, wie folgt aus:
public class MyClass : IMyInterface
{
public void Foo() { }
}
Dies erfüllt die Schnittstelle, weil es ein public
Mitglied auf der Klasse macht, dass jedes Mitglied an der Schnittstelle übereinstimmt. Dies ist, was in der Regel geschieht. Es ist jedoch möglich, explizit die Schnittstelle implementieren und die Schnittstellenfunktion zu einem private
Mitglied Karte:
public class MyClass : IMyInterface
{
void IMyInterface.Foo() { }
}
Dies schafft eine private Funktion auf MyClass
, die nur von externen Anrufern ist, wenn sie auf eine Instanz IMyInterface
beziehen. Zum Beispiel:
void Bar()
{
MyClass class1 = new MyClass();
IMyInterface class2 = new MyClass();
class1.Foo(); // works only in the first implementation style
class2.Foo(); // works for both
}
Explizite Implementierungen sind immer privat. Wenn Sie es außerhalb der Klasse aussetzen möchten, müssen Sie ein anderes Mitglied erstellen müssen und setzen, dass dann die explizite Implementierung verwenden, um die anderen Mitglied zu nennen. Dies erfolgt in der Regel so, dass ein Klasse-Schnittstellen ohne unübersichtlich seine öffentliche API implementieren kann, oder wenn zwei Schnittstellen Mitglieder mit dem gleichen Namen aus.
Andere Tipps
Da Sie die IDictionary sind Implementierung this
zu IDictionary<string,string>
haben:
public bool Equals(MySubRow other)
{
foreach (string key in ((IDictionary<string,string>)this).Keys) { }
}
ich glaube, beide Jared und Adam sind korrekt: die Eigenschaft explitcity auf der Basisklasse implementiert ist, was es nicht öffentlich zu sein. Sie sollten es zu ändern, um eine implizite Umsetzung der Lage sein, und machen es glücklich:
public class MyRow : IStringIndexable, System.Collections.IEnumerable,
ICollection<KeyValuePair<string, string>>,
IEnumerable<KeyValuePair<string, string>>,
IDictionary<string, string>
{
ICollection<string> Keys { }
}
protected
wird Vererbungsklassen erlauben es, um zu sehen, aber keine andere Klasse