Как переопределить свойство в C# через наследование интерфейса?
У меня есть интерфейс "IBase", который определяет обнуляемый int. Более поздний интерфейс "IDerived" скрывает обнуляемый тип int и "переопределяет" его как ненулевой.
interface IBase
{
int? Redefineable { get; set; }
}
interface IDerived : IBase
{
new int Redefineable { get; set; }
}
Класс, реализующий эти интерфейсы, должен явно реализовывать скрытое свойство, однако оно является закрытым, поэтому клиент не может его увидеть.
class TheClass : IDerived
{
public int Redefineable { get; set; }
int? IBase.Redefineable { get; set; }
}
Однако, несмотря на то, что это частная собственность, я могу получить к ней доступ через интерфейс IBase!
var o = new TheClass();
o.Redefineable = 1; // ok
var hack = o as IBase;
hack.Redefineable = null; // uh!
Это похоже на какое-то нарушение модификаторов доступа в C#, но в любом случае это не совсем то, что я имел в виду для переопределения (а не просто сокрытия) свойства. Это правильно в том смысле, что он делает то, что вы просите, получить интерфейс IBase, который имеет обнуляемое значение int, но это не интуитивно понятно для клиента, который затем может изменить неправильную версию свойства.
Что я действительно хочу, так это то, что если клиент обращается к IBase.Redefinable, он ведет себя так, как будто он обращается к свойству IDerived.Redefinable, "реальному" свойству TheClass. Таким образом, это на самом деле переопределено, как в обратной иерархии.
class TheClass : IDerived
{
public int Redefineable { get; set; }
int? IBase.Redefineable {
get {
// redirect to redefined property
return this.Redefineable;
}
set
{
// stop client setting it to null
if (!value.HasValue)
throw new InvalidOperationException();
// redirect to redefined property
this.Redefineable = value.Value;
}
}
}
Это похоже на хак, почти как если бы я что-то упустил, поэтому я хочу спросить, знает ли кто-нибудь лучший / альтернативный способ реализации переопределяемых свойств?
1 ответ
Однако, несмотря на то, что это частная собственность, я могу получить к ней доступ через интерфейс IBase!
Это не частная собственность. Это просто свойство, использующее явную реализацию интерфейса. Это означает, что он общедоступен через интерфейс, но доступен только через интерфейс. Явная реализация интерфейса в основном предназначена для того, чтобы можно было реализовать "противоречивые" интерфейсы, а также для того, чтобы "препятствовать" (но не запрещать) использованию некоторых методов интерфейса. Это не должно создавать впечатление, что участники не существуют вообще.
По сути, это звучит так, как будто вы не должны использовать наследование здесь - если вы не хотите, чтобы что-то могло действовать как IBase
Вы не должны наследовать от IBase
,