Реализация класса из 2 интерфейсов, которые разделяют некоторые части - PullRequest
5 голосов
/ 25 августа 2011

Не является ли следующая практика хорошей практикой?

public interface IMyImmutableData
{
    int Data { get;}
}

public interface IMyMutableData
{
    int Data { set;get;}//implements both get and set
}

public class MyData : IMyImmutableData, IMyMutableData
{
    public int Data{get;set;} //implements both IMyImmutableData, IMyMutableData
}

void Main()
{
    MyData myData = new MyData{Data=10};
    Console.WriteLine(myData.Data);
}

Причина, по которой я спрашиваю, состоит в том, что resharper выдает мне следующее предупреждение: «возможная неоднозначность при доступе через этот интерфейс»

Причина, по которой я хочу сделать это, заключается в том, что когда я создаю методы, которые используют класс MyData, я хотел бы отправить его как объекты IMyMutable или IMyImmutable, чтобы пользователи метода знали, что они могут ожидать, что метод обновить или не обновить переданный объект.

Ответы [ 5 ]

5 голосов
/ 25 августа 2011

Я думаю, что вы можете проигнорировать предупреждение Решарпера, поскольку неоднозначность является преднамеренной.

Однако обычно класс-оболочка используется для обеспечения доступа только для чтения к чему-либо, поэтому его нельзя привести к чему-либо, что делаетобеспечить больше функциональности.

public class MyReadonlyData : IMyReadonlyData {
    private MyData instance;

    public int Data {
        get {
            return instance.Data;
        }
    }

    public MyReadonlyData( MyData mydata ) {
        instance = mydata;
    }
}
// no access to original object or setters, period.
3 голосов
/ 25 августа 2011

Вам нужно сделать одну или обе реализации явными:

public int IMyImmutableData.Data { get; }
public int IMyMutableData.Data { get; set; }

Когда вы помечаете одно как явное, к нему можно получить доступ, только если оно специально приведено к этому типу:

MyData obj = new MyData();
obj.Data; // Doesnt exist
(obj as IMyImmutableData).Data // Exists, specifically cast as this interface

Если вы решите не отмечать одно как явное, это свойство будет выбрано при приведении к другим соответствующим типам.

2 голосов
/ 25 августа 2011

Я думаю, что в этом случае ваша структура в порядке.Вы не хотите явно реализовывать интерфейсы через отдельные свойства, потому что тогда Data, к которому вы получаете доступ через неизменяемый интерфейс, на самом деле будет отличным от значения для изменяемого интерфейса.

ТакжеВаш реальный код, вероятно, более сложный, потому что в этом случае нет никакой двусмысленности: вы обращаетесь к Data через сам объект, поэтому не нужно рассматривать интерфейсы.

Одно решение с явной реализацией интерфейса будетиспользовать общее вспомогательное поле, а не авто-свойства:

private int _data;
public int IMyImmutableData.Data
{
    get
    {
        return this._data;
    }
}

public int IMyMutableData.Data
{
    get
    {
        return this._data;
    }
    set
    {
        this._data = value;
    }
}
0 голосов
/ 26 августа 2011

Вам нужен комбинированный интерфейс с «новым» квалификатором в интерфейсе чтения-записи, чтобы избежать сбоев.Кроме того, ваши интерфейсы плохо названы.Лучшими именами будут что-то вроде «IReadableData», «IWritableData» и «IReadWriteData».Обратите внимание, что хотя «IReadableData» не предоставляет каких-либо средств изменения данных, это ни в коем случае не подразумевает, что данные являются неизменными.Если что-то неизменно, оно не будет никем измененоэто явно не относится к объекту типа MyData.

0 голосов
/ 25 августа 2011

Вы можете привести переменную и сообщить компилятору, что именно вы имеете в виду: (разрешить неоднозначность)

MyData myData = new MyData{Data=10};
Console.WriteLine( ((IMyMutableData)(myData)).Data );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...