将setter添加到C#interface

时间:2016-04-28 07:14:02

标签: c# inheritance properties interface

我有一个接口,只用Id方法声明了一些属性(仅在示例中缩写为get)。实现此接口的类不必为此属性提供公共setter:

public interface IMetadataColumns
{
    Int32 Id { get; }
}

现在我需要另一个具有相同属性的接口,但现在它们必须都是可写的。所以我添加了一个继承旧接口的新接口,其中每个属性也有一个setter:

public interface IMetadataColumnsWritable : IMetadataColumns
{
    Int32 Id { get; set; }
}

Visual Studio现在强调了这一点,并警告我如果隐藏旧属性,则使用new关键字。

我现在该怎么办?我有实现IMetadataColumns接口的类,它需要一些属性是只读的,但我也有其他类,其中那些相同的属性也必须是可写的。

我想隐藏一处房产听起来不像是要走的路......

3 个答案:

答案 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类型的引用获取。