Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getter and setter coming from different interfaces

Tags:

c#

interface

I really need to have something like this:

interface IReadableVar
{
    object Value { get; }
}

interface IWritableVar
{
    object Value { set; }
}

interface IReadableWritableVar : IReadableVar, IWritableVar
{
}

However when I try to use IReadableWritableVar.Value I get compile errors unless I explicitly cast to base interface, like here:

static void Main()
{
    IReadableWritableVar var = null;
    var t = var.Value;  // <-- CS0229: Ambiguity between 'IReadableVar.Value' and 'IWritableVar.Value'
    var.Value = null;   // <-- CS0229: Ambiguity between 'IReadableVar.Value' and 'IWritableVar.Value'

    var v = ((IReadableVar)var).Value;  // compiles fine
    ((IWritableVar)var).Value = null;   // compiles fine
}

Why do I get these errors although everything should be clear to the compiler? Is there any way to fix this problem other than casting (hundreds of places in the application)?

Update: it was suggested this is a dupe of Implementing 2 Interfaces with 'Same Name' Properties but this is slightly different as in the other case there's no inheritance in interfaces. Anyway, the problem is solved now - see accepted answer.

like image 340
Arek Avatar asked Apr 20 '17 09:04

Arek


People also ask

CAN interface have getters and setters?

Technically the class that implements the interface is free to use a property or a getter. In the same way there is no way for us to specify that a property is a setter in an interface, but we can still use a setter in our class.

How do you use setters and getters in two different classes?

To fix this, you need to pass a reference to the GetterAndSetter instance from class A to B . You can do this e.g. by passing it as a parameter to a method of B , or by creating a new instance of A in B and calling a method that provides an instance of GetterAndSetter .

Can we use getter and setter in interface in Java?

Getter and Setter are methods used to protect your data and make your code more secure. Getter returns the value (accessors), it returns the value of data type int, String, double, float, etc.

CAN interface have getters and setters C#?

You CAN use both get and set in interface property!


3 Answers

Interesting question. I think extension methods will help in this case.

public static class Extension
{
    public static object GetValue(this IReadableVar v)
    {
        return v.Value;
    }

    public static void SetValue(this IWritableVar v, object value)
    {
        v.Value = value;
    }
}

You need to change the code to use it:

IReadableWritableVar variable = null;
var t = variable.GetValue();
variable.SetValue(null);

The extension method does the cast for you.

like image 33
Cheng Chen Avatar answered Sep 25 '22 16:09

Cheng Chen


A possible workaround can be modify your interface IReadableWritableVar like this:

interface IReadableWritableVar : IReadableVar, IWritableVar
{
    new object Value { get; set; }
}

But keep in my that a valid implementation should be:

class ReadableWritableVar : IReadableWritableVar
{
    public object Value
    {
        get { throw new NotImplementedException(); }
        set { throw new NotImplementedException(); }
    }

    object IWritableVar.Value
    {
        set { throw new NotImplementedException(); }
    }

    object IReadableVar.Value
    {
        get { throw new NotImplementedException(); }
    }
}

A more concrete example:

class ReadableWritableVar : IReadableWritableVar
{
    public object Value
    {
        get { return ((IReadableVar)this).Value; }
        set { ((IWritableVar)this).Value = value; }
    }

    object _val;

    object IWritableVar.Value { set { _val = value; } }

    object IReadableVar.Value => _val;
}

Or even better:

class ReadableWritableVar : IReadableWritableVar
{
    public object Value { get; set; }

    object IWritableVar.Value { set { Value = value; } }

    object IReadableVar.Value => Value;
}
like image 160
Alessandro D'Andria Avatar answered Sep 21 '22 16:09

Alessandro D'Andria


Well, effectively Getter and Setter are just two methods. When we use IReadableWritableVar interface there are two methods with identical name inherited from base interfaces and compiler doesn't know which of these two should it use hence the ambiguity.

When we cast that to one of these interfaces the other member's gone and there's no error.

If we implement those member there will be no error as compiler will use that implementation:

class ReadableWritableVar : IReadableWritableVar
{
    public object Value { get; set; }
}

var @var = new ReadableWritableVar();
var t = @var.Value;

Also you can use an explicit interface members implementation from @Alessandro D'Andria's answer if it is required that you use interface and not class.

like image 39
Fabjan Avatar answered Sep 22 '22 16:09

Fabjan