【发布时间】:2015-01-26 17:12:34
【问题描述】:
我有一个接口“IBase”,它指定了一个可为空的 int。稍后的接口“IDerived”隐藏了可为空的 int 并将其“重新定义”为不可为空。
interface IBase
{
int? Redefineable { get; set; }
}
interface IDerived : IBase
{
new int Redefineable { get; set; }
}
实现这些接口的类必须显式实现 hidden 属性,但它是私有的,因此客户端看不到它。
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# 访问修饰符,但无论哪种方式,这都不是我重新定义(不仅仅是隐藏)属性的真正想法。从某种意义上说,它按照您的要求进行操作,获得一个可以为空的 int 的 IBase 接口,但这对于可以修改 wrong 版本属性的客户端来说是不直观的。
我真正想要的是,如果客户端访问 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;
}
}
}
这感觉就像一个 hack,几乎好像我错过了什么,所以我想问是否有人知道实现可重新定义属性的更好/替代方法?
【问题讨论】:
-
我认为您需要重新了解多态性的工作原理。如果你有一个
IBase并且你正在使用它的属性,那将是IBase定义它的方式。如果您有一个IDerived并且您正在使用它的属性,那么它将是IDerived定义它的方式。 -
这就是它的工作原理。
-
显式接口实现不是通常意义上的
private。因此,不允许为它们指定private修饰符。 -
使用
new修饰符隐藏一个成员(这里是一个属性)是不是“重新定义”它。它只是介绍另一个看起来相同的成员。这很少是一件好事。原始成员不会被删除,并且始终可以通过向上转换为定义它的类型(这里是基接口)来使用它。 -
显式接口实现只是为了解决歧义问题,因为必须实现两个同名成员。这不是访问限制。
标签: c# properties interface redefine explicit-interface