Можно ли реализовать параметр для реализации двух интерфейсов?
Можно ли определить функцию, которая принимает параметр, который должен реализовывать два интерфейса?
(Два интерфейса - это те, которые я только что вспомнил с головы, а не те, которые я хочу использовать)
private void DoSomthing(IComparable, ICollection input)
{
}
Ответы
Ответ 1
Вы можете:
1) Определите интерфейс, наследующий оба требуемых интерфейса:
public interface ICombinedInterface : IComparable, ICollection {... }
private void DoSomething(ICombinedInterface input) {... }
2) Используйте generics:
private void DoSomething<T>(T input)
where T : IComparable, ICollection
{...}
Ответ 2
Вы можете наследовать другой интерфейс от этих двух интерфейсов и сделать свой параметр реализующим этот интерфейс.
Ответ 3
Хорошо, да, и нет.
Вы можете, как предположил Стив, создать другой, третий, интерфейс, который спускается с двух желаемых, и использовать это для типа параметра.
Однако это также потребует, чтобы используемый класс реализовывал и этот третий интерфейс.
Другими словами, это не сработает:
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%, что не буду давать вам других проблем, хотя мне придется подумать об этом.
Ответ 4
Общий подход к функциям, упомянутый выше, является хорошим, с одним большим предостережением: для того, чтобы придать тип объекту, чтобы он мог быть передан подпрограмме с несколькими общими ограничениями, нужно знать тип, который отвечает этим ограничениям, и родительский тип объекта. Подпрограмма, которая принимает такой объект, будет знать такой тип (он передавался как параметр родового типа), но нет никакого прекрасного способа для класса сохранить эту информацию и использовать ее позже. Если множество не связанных между собой типов реализуют как IFoo, так и IBar, было бы сложно разработать процедуру, которая могла бы принимать множество несвязанных экземпляров объектов, хранить их в списке или что-то еще, а затем передавать все элементы в списке подпрограмму с общим параметром IFoo + IBar.
Если такой сценарий может потребоваться, наилучшим подходом было бы иметь не общий вариант для каждой общей процедуры, которая принимала бы, например, параметр типа IFoo и при необходимости переведите его в IBar. Затем можно было сохранить все элементы в списке <IFoo> и передать их рутине. Можно было бы потерять тип безопасности универсального метода, но иногда идеальная безопасность типа не достижима.