Свойство C # недоступно в производном классе - PullRequest
5 голосов
/ 27 января 2010

Я не уверен, что происходит. У меня есть следующий базовый класс:

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 ]

8 голосов
/ 27 января 2010

Вы реализуете свойство 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
}

Явные реализации всегда private. Если вы хотите представить его за пределами класса, вам нужно будет создать другого члена и представить его, а затем использовать явную реализацию для вызова другого члена. Обычно это делается для того, чтобы класс мог реализовывать интерфейсы, не загромождая свой общедоступный API, или если два интерфейса предоставляют члены с одинаковым именем.

3 голосов
/ 27 января 2010

Поскольку вы реализуете интерфейс IDictionary в явном виде, вам сначала нужно привести this к IDictionary<string,string>:

public bool Equals(MySubRow other)
{
    foreach (string key in ((IDictionary<string,string>)this).Keys) { }
}
0 голосов
/ 27 января 2010

protected позволит наследовать классы, чтобы увидеть его, но нет другого класса

0 голосов
/ 27 января 2010

Я считаю, что и Джаред, и Адам правы: свойство explitcity реализовано в базовом классе, поэтому оно не является публичнымВы должны иметь возможность изменить его на неявную реализацию и сделать его счастливым:

public class MyRow : IStringIndexable, System.Collections.IEnumerable,
    ICollection<KeyValuePair<string, string>>,
    IEnumerable<KeyValuePair<string, string>>,
    IDictionary<string, string>
{
    ICollection<string> Keys { }
}
...