Свойство C# недоступно в производном классе
Я не уверен, что происходит. У меня есть следующий базовый класс:
public class MyRow : IStringIndexable, System.Collections.IEnumerable,
ICollection<KeyValuePair<string, string>>,
IEnumerable<KeyValuePair<string, string>>,
IDictionary<string, string>
{
ICollection<string> IDictionary<string, string>.Keys { }
}
И тогда у меня есть этот производный класс:
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) { }
}
}
Почему я получаю эту ошибку? "MyNamespace.MyRow" не содержит определения "Keys". Оба класса находятся в MyNamespace
Пространство имен. Я пытался получить доступ this.Keys
а также base.Keys
и ни один не работает изнутри MySubRow
, Я пытался пометить Keys
собственность как public
в MyRow
но я получил "Модификатор public" недопустим для этого элемента ", я думаю, потому что это необходимо для реализации интерфейса.
4 ответа
Вы реализуете Keys
свойство явно. Если вы хотите сделать этого участника общедоступным (или protected
), менять IDictionary<string, string>.Keys
в Keys
и добавьте соответствующий модификатор видимости перед ним.
public ICollection<string> Keys { ... }
или же
protected ICollection<string> Keys { ... }
Вы могли бы ссылаться base
как пример IDictionary<string, string>
также:
((IDictionary<string, string>)base).Keys
Дополнительная информация
(Судя по вашим комментариям, вы, кажется, знакомы с различием, но другие могут и не быть)
Реализация интерфейса C# может быть выполнена двумя способами: неявно или явно. Давайте рассмотрим этот интерфейс:
public interface IMyInterface
{
void Foo();
}
Интерфейс - это просто контракт на то, какие члены класс должен сделать доступным для кода, который его вызывает. В этом случае у нас есть одна функция с именем Foo
это не принимает никаких параметров и ничего не возвращает. Неявная реализация интерфейса означает, что вы должны предоставить public
элемент, который соответствует имени и подписи члена на интерфейсе, как это:
public class MyClass : IMyInterface
{
public void Foo() { }
}
Это удовлетворяет интерфейсу, потому что он выставляет public
член класса, который соответствует каждому члену интерфейса. Это то, что обычно делается. Тем не менее, можно явно реализовать интерфейс и отобразить функцию интерфейса на private
член:
public class MyClass : IMyInterface
{
void IMyInterface.Foo() { }
}
Это создает частную функцию на MyClass
это доступно только внешним абонентам, когда они ссылаются на экземпляр IMyInterface
, Например:
void Bar()
{
MyClass class1 = new MyClass();
IMyInterface class2 = new MyClass();
class1.Foo(); // works only in the first implementation style
class2.Foo(); // works for both
}
Явные реализации всегда закрыты. Если вы хотите представить его за пределами класса, вам нужно будет создать другого члена и предоставить его, а затем использовать явную реализацию для вызова другого члена. Обычно это делается для того, чтобы класс мог реализовывать интерфейсы, не загромождая свой общедоступный API, или если два интерфейса предоставляют члены с одинаковыми именами.
Так как вы реализуете интерфейс IDictionarythis
в IDictionary<string,string>
:
public bool Equals(MySubRow other)
{
foreach (string key in ((IDictionary<string,string>)this).Keys) { }
}
Я считаю, что и Джаред, и Адам правы: свойство explitcity реализовано в базовом классе, поэтому оно не является публичным. Вы должны иметь возможность изменить его на неявную реализацию и сделать его счастливым:
public class MyRow : IStringIndexable, System.Collections.IEnumerable,
ICollection<KeyValuePair<string, string>>,
IEnumerable<KeyValuePair<string, string>>,
IDictionary<string, string>
{
ICollection<string> Keys { }
}
protected
позволит наследовать классы, чтобы увидеть его, но нет другого класса