Можно ли заставить параметр реализовать два интерфейса? - PullRequest
23 голосов
/ 21 апреля 2009

Можно ли определить функцию, которая принимает параметр, который должен реализовывать два интерфейса?

(Два интерфейса - это те, которые я только что вспомнил на макушке; не те, которые я хочу использовать)

private void DoSomthing(IComparable, ICollection input)
{

}

Ответы [ 4 ]

52 голосов
/ 21 апреля 2009

Вы можете:

1) Определите интерфейс, который наследует оба обязательных интерфейса:

public interface ICombinedInterface : IComparable, ICollection {... }

private void DoSomething(ICombinedInterface input) {... }

2) Используйте дженерики:

private void DoSomething<T>(T input)
    where T : IComparable, ICollection
{...}
5 голосов
/ 21 апреля 2009

Вы можете наследовать другой интерфейс от этих двух интерфейсов и заставить ваш параметр реализовать этот интерфейс.

2 голосов
/ 21 апреля 2009

Ну да, и нет.

Вы можете, как предложил Стив, создать еще один, третий, интерфейс, который наследуется от двух, которые вы хотите, и использовать его для типа параметра.

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

Другими словами, это не сработает:

public interface I1 { }
public interface I2 { }
public class C : I1, I2 { }

public interface I3 : I1, I2 { }
public class YourClass
{
    public void Test(I3 i) { }
}

...
YourClass yc = new YourClass();
C c = new C();
yc.Test(c); // won't work, C does not implement I3

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

public class YourClass
{
    public void Test<T>(T i) where T: I1, I2 { }
}

Теперь это будет работать. Я все еще не уверен на 100%, что это не вызовет у вас других проблем, но я должен подумать об этом.

1 голос
/ 04 августа 2011

Упомянутый выше подход к универсальной функции является хорошим, с одним большим предостережением: для того, чтобы типизировать объект так, чтобы он мог быть передан в процедуру с несколькими общими ограничениями, необходимо знать тип, который удовлетворяет этим ограничениям и родительский тип объекта приведения. Подпрограмма, которая принимает такой объект, будет знать такой тип (он был передан как параметр универсального типа), но у класса нет хорошего способа сохранить эту информацию и использовать ее позже. Если различные несвязанные типы реализуют как IFoo, так и IBar, было бы трудно спроектировать подпрограмму, которая могла бы принимать несколько не связанных экземпляров объекта, сохранять их в списке или чем-то еще, а затем передавать все элементы в списке подпрограмме. с общим параметром IFoo + IBar.

Если такой сценарий может быть необходим, наилучшим подходом было бы иметь неуниверсальный аналог для каждой общей процедуры, который мог бы принять, например, параметр типа IFoo и приведите его к IBar по мере необходимости. Затем можно сохранить все элементы в списке и передать их в процедуру. Можно было бы потерять безопасность типов универсального метода, но иногда идеальная безопасность типов не достижима.

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