How to redefine a property in C# through interface inheritance?

I have an interface 'IBase' that specifies a nullable int. A later interface 'IDerived' hides the nullable int and 'redefines' it as non-nullable.

interface IBase
{
    int? Redefineable { get; set; }
}

interface IDerived : IBase
{
    new int Redefineable { get; set; }
}

The class that implements these interfaces must explicitly implement the hidden property, however it's private so the client can't see it.

class TheClass : IDerived
{
    public int Redefineable { get; set; }
    int? IBase.Redefineable { get; set; }
}

However, even though it's a private property, I can still access it through the IBase interface!

var o = new TheClass();
o.Redefineable = 1; // ok

var hack = o as IBase;
hack.Redefineable = null; // uh!

This seems like some kind of violation of C# access modifiers, but either way it isn't really what I had in mind for redefining (not just hiding) a property. It's correct in the sense that it does what you're asking, get an IBase interface which has a nullable int but this is non-intuitive to the client who could then modify the wrong version of the property.

What I really want, is that if the client accesses IBase.Redefinable, then it behaves as if it's accessing the IDerived.Redefinable property, the 'real' property of TheClass. That way it's actually redefined, as in back through the hierarchy.

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

This just feels like a hack, almost as if I'm missing something, so I want to ask if anyone knows a better/alternative way to implement re-definable properties?

Jon Skeet
people
quotationmark

However, even though it's a private property, I can still access it through the IBase interface!

It's not a private property. It's just a property using explicit interface implementation. That means it's public through the interface, but only available through the interface. Explicit interface implementation is mostly designed to make it feasible to implement "contradictory" interfaces, as well as being used to "discourage" (but not prohibit) the use of some interface methods. It's not meant to give the impression that the members don't exist at all.

Fundamentally, it sounds like you shouldn't be using inheritance here - if you don't want something to be able to act as an IBase, you shouldn't inherit from IBase.

people

See more on this question at Stackoverflow