Свойство 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, или если два интерфейса предоставляют члены с одинаковыми именами.

Так как вы реализуете интерфейс IDictionary явно, вы должны сначала привести this в 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 позволит наследовать классы, чтобы увидеть его, но нет другого класса

Другие вопросы по тегам