9

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?

leora
  • 188,729
  • 360
  • 878
  • 1,366

5 Answers5

7

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
  • 187,081
  • 35
  • 232
  • 306
7

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
  • 13,543
  • 2
  • 56
  • 59
3

+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
  • 122,288
  • 32
  • 173
  • 203
2

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
  • 16,751
  • 5
  • 52
  • 60
  • 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 Jan 17 '09 at 12:50
  • 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 Jan 17 '09 at 12:50
  • You're absolutely right, I did miss the point, I read it wrong. – Patrik Hägne Jan 17 '09 at 12:52
  • 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 Jan 17 '09 at 14:00
  • 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 Jan 17 '09 at 14:12
0

If property getters and setters were independent entities, an interface that defined a property setter and inherited from one that defined a property getter would allow read-write semantics. Unfortunately, for whatever reason, neither vb.net nor C# will allow that to work. Instead, getters are read-only properties, and setters are write-only properties. If a type defines a write-only property but inherits a read-only property, vb.net and C# will only see the write-only property. If an interface inherits an interface which exposes a read-only property and an interface which exposes a write-only property, neither property will be usable on the interface because neither vb.net nor C# is willing to use the fact that a property is being read or written to determine whether to use the read-only or write-only property. Instead, both languages will declare that the property is "ambiguous".

As noted, the solution is to have an interface which inherits one with a read-only property and implements a read-write property. This will hide the other read-only property, but if the read-write property is implemented to return the same data, that shouldn't be a problem. Indeed, the way implicit interface implementation is handled in C# allows both the read-write and read-only interface to be implemented using the same code (vb, somewhat annoyingly, would require the 'read-only' property to be coded separately from the 'read-write' property).

supercat
  • 77,689
  • 9
  • 166
  • 211