我有一个接口,只用Id
方法声明了一些属性(仅在示例中缩写为get
)。实现此接口的类不必为此属性提供公共setter:
public interface IMetadataColumns
{
Int32 Id { get; }
}
现在我需要另一个具有相同属性的接口,但现在它们必须都是可写的。所以我添加了一个继承旧接口的新接口,其中每个属性也有一个setter:
public interface IMetadataColumnsWritable : IMetadataColumns
{
Int32 Id { get; set; }
}
Visual Studio现在强调了这一点,并警告我如果隐藏旧属性,则使用new
关键字。
我现在该怎么办?我有实现IMetadataColumns
接口的类,它需要一些属性是只读的,但我也有其他类,其中那些相同的属性也必须是可写的。
我想隐藏一处房产听起来不像是要走的路......
答案 0 :(得分:15)
当涉及到界面时,new
关键字并不意味着您隐藏属性的方式与类相同。
实施IMetadataColumnsWritable
的班级只会有一个Id
,无论您是否将其投放到基础IMetadataColumns
界面(除非您添加了readonly属性的显式实现 - 但这不是必需的,只会在这种情况下允许错误。)
换句话说,你可能有:
// this interface is public, and it allows everyone to read the Id
public interface IMetadataColumns
{
int Id { get; }
}
// this one is writeable, but it's internal
internal interface IMetadataColumnsWritable : IMetadataColumns
{
// we need to use 'new' here, but this doesn't mean
// you will end up with two getters
new int Id { get; set; }
}
// internal implementation is writeable, but you can pass it
// to other assemblies through the readonly IMetadataColumns
// interface
internal class MetadataColumns : IMetadataColumnsWritable
{
public int Id { get; set; }
}
因此,除非您将readonly属性明确地实现为单独的属性,否则您将只有一个属性,无论您使用哪个接口来访问它:
var columns = new MetadataColumns { Id = 5 };
var x = (columns as IMetadataColumns).Id;
var y = (columns as IMetadataColumnsWritable).Id;
Debug.Assert(x == y);
另一方面,使用new
关键字隐藏班级内的成员是我在大多数情况下不推荐的内容,因为它基本上会创建一个全新的成员,恰好被称为与基类中的不同成员相同。
答案 1 :(得分:2)
您确实应该在此处使用new
关键字。在类实现中,您必须实现这两个属性(因为您并没有真正隐藏属性)。如果它们具有不同的返回类型,则必须至少其中一个必须明确实现。
public class X : IMetadataColumnsWritable
{
public int Id
{
get;
set;
}
// only necessary if you have to differentiate on the implementation.
int IMetadataColumns.Id
{
get
{
return this.Id; // this will call the public `Id` property
}
}
}
答案 2 :(得分:2)
使用getter only version的显式实现转发到公共版本是否有效?
int IMetadataColumns.Id {
get {
return this.Id;
}
}
public Id {
get { … }
set { … }
}
您可能会发现公开版本确实需要new
,但显式版本将通过IMetadataColumns
类型的引用获取。