17

I have an interface that declares some properties (shortened to Id only in the example) with only a get method. Classes implementing this interface do not have to provide a public setter for this property:

public interface IMetadataColumns
{
    Int32 Id { get; }
}

Now I need another interface with the same properties, but now they must all be writable as well. So I added a new interface inheriting from the old one where each property also has a setter:

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

Visual Studio now underlines this and warns me to use the new keyword if hiding the old properties was intended.


What shall I do now? I have classes implementing the IMetadataColumns interface which need some of the properties to be read-only, but I also have other classes where exactly those same properties must be writable as well.

I guess hiding a property sounds somehow not like the way to go...

1
  • 1
    i think hiding the property is the correct way to go, the classes which implement IMetadataColumns will still have read only property and the classes which implement IMetadataColumnsWritable will have the read/write property.
    – Dr. Stitch
    Commented Apr 28, 2016 at 7:22

3 Answers 3

22

When interfaces are involved, the new keyword doesn't mean you are hiding the property in the same sense as with classes.

Your class implementing IMetadataColumnsWritable will only have one Id, regardless of whether you cast it to the base IMetadataColumns interface or not (unless you add an explicit implementation for the readonly property - but this is not needed and would only allow for errors in this case).

In other words, you might have:

// 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; }
}

So, unless you explicitly implement the readonly property as a separate one, you will have only a single property, whichever interface you use to access it:

var columns = new MetadataColumns { Id = 5 };

var x = (columns as IMetadataColumns).Id;
var y = (columns as IMetadataColumnsWritable).Id;

Debug.Assert(x == y);

Hiding a member inside the class using the new keyword, on the other hand, is what I would not recommend in most cases, because it basically creates a completely new member, which just happens to be called the same as a different member in the base class.

2
  • @PatrickHofman: Only if you implement the other one explicitly, which you don't have to.
    – vgru
    Commented Apr 28, 2016 at 7:22
  • So that means if I have a class implementing the writable interface that uses the new keyword to hide the read-only declaration, will an instance of that class casted to IMetadataColumns have a different underlying property than when it's casted to IMetadataColumnsWritable or not? Commented Apr 28, 2016 at 7:22
2

You should indeed use the new keyword here. In your class implementation, you have to implement both properties (since you are not really hiding the property). If they have different return types, at least one of them has to be implemented explicitly.

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
        }
    }
}
1
  • So you're saying that I don't need the int IMetadataColumns.Id { ... } part if there's no logic and the readable and read-writable property shall just be the same when it comes to reading the value? Commented Apr 28, 2016 at 7:26
2

Does using explicit implementation of the getter only version forwarding to a public version work?

int IMetadataColumns.Id { 
  get { 
    return this.Id;
  }
}

public Id {
  get { … }
  set { … }
}

You might find the public version does need to be new, but the explicit version will be picked up by references of type IMetadataColumns.

4
  • No need to cast the this.Id in the explicit Id. Commented Apr 28, 2016 at 7:21
  • @PatrickHofman I tend to include it as a defensive and consistency measure (albeit sometimes unneccessary0.
    – Richard
    Commented Apr 28, 2016 at 7:29
  • It could lead to problems too when changing interfaces. Commented Apr 28, 2016 at 7:29
  • @PatrickHofman: True, but equally without the cast it could as well (eg. I was tempted to have an explicit implementation of IMetadataColumnsWritable.Id as well, and to a degree the cast is hangover from that... thus removing).
    – Richard
    Commented Apr 28, 2016 at 7:32

Not the answer you're looking for? Browse other questions tagged or ask your own question.