C # Интерфейс с методом, который возвращает реализацию нескольких интерфейсов - PullRequest
3 голосов
/ 16 января 2011

При работе с интерфейсами я часто сталкиваюсь со случаем, когда я хочу убедиться, что возвращаемое значение из свойства или метода, или иногда параметра метода, реализует ДВА или более интерфейсов без создания нового интерфейса.

Мой конкретный пример сейчас заключается в том, что я хочу указать, что метод приведет к IEnumerable<SomeType>, который также поддерживает INotifyCollectionChanged - таким образом, другому объекту, использующему интерфейс, не нужно типизировать и все же иметь доступ к обоим параметрам,(Я не хочу использовать ReadOnlyObservableCollection явно, потому что он хорошо работает только с ObservableCollection объектами, но я также хотел бы оставить параметр открытым для будущих разработчиков интерфейса, чтобы использовать его, если они захотят.)

Я думаю, что это можно сделать только с параметрами метода, а не с возвращаемыми значениями, предоставив объявление метода следующим образом:

void SetStringData<T>(T data) where T : IEnumerable<string>, INotifyCollectionChanged

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

(IEnumerable<string>, INotifyCollectionChanged) GetStringData()

Есть предложения, как мне это сделать?Или, если это не удастся, как я смогу добиться таких же результатов?

Ответы [ 5 ]

2 голосов
/ 16 января 2011

Нет хорошего решения, но я предпочитаю добавить контрактный код в интерфейс. Тем не менее, требуется, чтобы вызывающая сторона приводила результат к нужному интерфейсу.

Что-то вроде:

Contract.Ensures(Contract.Result<object>() is IEnumerable<string>);
Contract.Ensures(Contract.Result<object>() is INotifyCollectionChanged);
2 голосов
/ 16 января 2011

Единственный способ увидеть, как это делается, - использовать dynamic, поскольку все это разрешается во время выполнения, например:

public dynamic GetStringData()
{

}

И:

IDisposable disposable = GetStringData();
ISomeOtherInterface other = GetStringData();

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

public IComposite GetStringData()
{

}

И:

IEnumerable<string> enumerable = GetStringData();
1 голос
/ 30 апреля 2011

Вы можете создать другую абстракцию (адаптер), которая кэширует возвращаемое значение и предоставляет отдельные средства доступа для различных типов, которые вам нужны. Таким образом, клиентский код защищен от тестирования и приведения. Вы можете вернуть этот адаптер вместо исходного возвращаемого значения.

Или вы можете просто вернуть кортеж с желаемыми выходами.

0 голосов
/ 24 января 2011

Что вы знаете о конкретном типе объектов, которые будет возвращать метод? Если вы знаете, что возврат из интерфейса будет Widget, и что Widget поддерживает IEnumerable и INotifyCollectionChanged, вы можете определить функцию для возврата Widget. Если вы знаете, что возвращаемый тип будет классом, который вы будете разрабатывать для указанной цели, но вы точно не знаете, каким он будет, вы можете определить новый интерфейс INotifiableEnumerable, который наследуется от IEnumerable и INotifyCollectionChanged и иметь любой класс, который вы будете возвращать реализовать INotifiableEnumerable. Обратите внимание, что в последнем случае ваша функция не сможет возвращать классы, которые явно не реализуют INotifiableEnumerable, даже если они реализуют как IEnumerable, так и INotifyCollectionChanged.

0 голосов
/ 16 января 2011

Возможно, подойдет общий метод?

T GetStringData<T>()

И добавить некоторые ограничения к T

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...