tags:

views:

304

answers:

4

If i have an interface:

interface IFoo
{
    int Offset {get;}
}

can i have this:

interface IBar: IFoo
{   
    int Offset {set;}
}

so consumers of IBar will be able to set or get?

+7  A: 

This is close but no banana.

interface IFoo
{
 int Offset { get; }
}

interface IBar : IFoo
{
 new int Offset { set; }
}

class Thing : IBar
{
 public int Offset { get; set; }
}

Note the new keyword in IBar, but this overrides the get accessor of IFoo so IBar doesn't have a get. Hence no you can't actually create IBar that simply adds a set whilst keeping the existing get.

AnthonyWJones
No, it doesn't... Not completly...
Arjan Einbu
Anthony you tested *class* inherited from IBar, but question is about consumers of IBar interface
aku
Your code compiles, but using the IBar interface to call Thing's setter won't compile.
Arjan Einbu
Arjan, you are spot on.
AnthonyWJones
+6  A: 

No, you can't!

(I was about to write "Yes", but after reading Anthony's post, and trying out a few tweaks, I found the answer to be NO!)

class FooBar : IFoo, IBar
{
    public int Offset{get;set;}
}

(Will generate a warning as Anthony points out, which can be fixed by adding the "new" keyword.)

When trying out the code:

IBar a = new FooBar();
a.Offset = 2;
int b = a.Offset;

The last line will generate a compile error, since you have hidden IBar's Offset setter.

EDIT: Fixed the accesibillity modifier on the property in the class. Thx Anthony!

Arjan Einbu
Note in my answer the Offset property is public in the class.
AnthonyWJones
+1 good answer. @ak this is the answer to accept.
AnthonyWJones
+3  A: 

+1 to Arjan Einbu

Of course consumers of IBar won't be able to get value of Offset property because inheritance of IFoo doesn't change semantic of Offset property defined in IBar - compiler warns you for a reason. When you use "new" keyword compiler completely removes disambiguation and treats IBar.Offset as write-only. However consumers of class inherited from IBar interface will be able to get and set Offset property.

There difference becomes more noticeable if you use explicit interface implementation:

class Boo: IBar
{
    int IFoo.Offset { get { return 0; } }
    int IBar.Offset 
    {
          set { }  // OK - IBar has a setter
          get { return 1; } // compiler error - IBar.Offset doesn't inherit setter

    }
}

class Program
{
    static void Main(string[] args)
    {
        Boo b = new Boo();
        int x = ((IFoo) b).Offset; // OK - IFoo.Offset has getter
        ((IBar) b).Offset = 1; // OK - IBar.Offset has setter
        x = ((IBar) b).Offset; // compiler error - IBar doesn't inherit 
                               // getter from IFoo
    }
}
aku
Good example, using the implicit implentation!
Arjan Einbu
+1  A: 

What you could do is having the IBar-interface having the getter and the setter (there's really no point of not having this). When you only have the setter in IBar you're really explicitly saying that "on the IBar interface the Offset propery is write only", this is obviously not what you want.

interface IFoo 
{ 
    int Offset { get;}
}

interface IBar : IFoo 
{
    new int Offset { get; set; } 
}

class Thing : IBar 
{
    public int Offset
    {
        get;
        set;
    }
}

Now you can use the class Thing like this:

var t = new Thing();
t.Offset = 1;
int read = t.Offset;
Patrik Hägne
Patrik, you missed the point - consumers of IBar won't be able to get value. Consumers of class that implicitly implement IBar will be able to get/set. In case of explicity implementation you wont' be able to access Offset property directly
aku
Same problem as Anthony's example: Your code compiles, but using the IBar interface to call Thing's setter still won't compile.
Arjan Einbu
You're absolutely right, I did miss the point, I read it wrong.
Patrik Hägne
Edited my answer to reflect this, now it works.
Patrik Hägne
It works because you're changing the Interface. Now you're hiding IFoo's setter. It is now possible to have two different setters using implicit iterface implemtation.
Arjan Einbu
Yes, and I point that out. The Offset property on IBar has a getter and a setter, there is no reason for bar to be write only when the wanted behavior is to have it set and get.
Patrik Hägne