Propriedade C# não disponível na classe derivada
-
23-09-2019 - |
Pergunta
Não tenho certeza do que está acontecendo.Eu tenho a seguinte classe base:
public class MyRow : IStringIndexable, System.Collections.IEnumerable,
ICollection<KeyValuePair<string, string>>,
IEnumerable<KeyValuePair<string, string>>,
IDictionary<string, string>
{
ICollection<string> IDictionary<string, string>.Keys { }
}
E então eu tenho esta classe derivada:
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) { }
}
}
Por que recebo esse erro?"'MyNamespace.MyRow' não contém uma definição para 'Keys'".Ambas as turmas estão no MyNamespace
espaço para nome.Eu tentei acessar this.Keys
e base.Keys
e nenhum dos dois funciona por dentro MySubRow
.Eu tentei marcar o Keys
propriedade como public
em MyRow
mas obtive "O modificador 'público' não é válido para este item", acho que é necessário implementar uma interface.
Solução
Você está implementando o Keys
propriedade explicitamente. Se você deseja tornar esse membro acessível publicamente (ou protected
), mudança IDictionary<string, string>.Keys
para Keys
e adicione o modificador de visibilidade apropriado na frente dele.
public ICollection<string> Keys { ... }
ou
protected ICollection<string> Keys { ... }
Você pode fazer referência base
Como uma instância de IDictionary<string, string>
também:
((IDictionary<string, string>)base).Keys
Mais Informações
(A julgar pelos seus comentários, você parece estar familiarizado com a distinção, mas outros podem não ser)
A implementação da interface C# pode ser feita de duas maneiras: implicitamente ou explicitamente. Vamos considerar esta interface:
public interface IMyInterface
{
void Foo();
}
Uma interface é apenas um contrato para o que os membros uma classe deve disponibilizar para o código que está chamando. Nesse caso, temos uma função chamada Foo
Isso não leva parâmetros e não retorna nada. Uma implementação implícita de interface significa que você deve expor um public
Membro que corresponde ao nome e assinatura do membro na interface, assim:
public class MyClass : IMyInterface
{
public void Foo() { }
}
Isso satisfaz a interface porque expõe um public
Membro da classe que corresponde a todos os membros na interface. Isso é o que geralmente é feito. No entanto, é possível explicitamente implementar a interface e mapear a função de interface para um private
membro:
public class MyClass : IMyInterface
{
void IMyInterface.Foo() { }
}
Isso cria uma função privada em MyClass
isso só é acessível a chamadores externos quando eles estão se referindo a uma instância de IMyInterface
. Por exemplo:
void Bar()
{
MyClass class1 = new MyClass();
IMyInterface class2 = new MyClass();
class1.Foo(); // works only in the first implementation style
class2.Foo(); // works for both
}
Implementações explícitas são sempre privado. Se você deseja expor -o fora da classe, terá que criar outro membro e expor isso, use a implementação explícita para ligar para o outro membro. Isso geralmente é feito para que uma classe possa implementar interfaces sem atravessar sua API pública ou se duas interfaces expõem os membros com o mesmo nome.
Outras dicas
Como você está implementando explicitamente a interface IDictionary<TKey,TValue>, primeiro você precisa converter this
para IDictionary<string,string>
:
public bool Equals(MySubRow other)
{
foreach (string key in ((IDictionary<string,string>)this).Keys) { }
}
Acredito que Jared e Adam estão corretos: a propriedade é explicada na classe base, resultando em não ser pública. Você deve ser capaz de alterá -lo para uma implementação implícita e torná -lo feliz:
public class MyRow : IStringIndexable, System.Collections.IEnumerable,
ICollection<KeyValuePair<string, string>>,
IEnumerable<KeyValuePair<string, string>>,
IDictionary<string, string>
{
ICollection<string> Keys { }
}
protected
permitirá que as aulas de herdador o vejam, mas nenhuma outra classe