28

Is it possible to define a function that takes in a parameter that must implement two interfaces?

(The two interfaces are ones I just remembered off the top of my head; not the ones I want to use)

private void DoSomthing(IComparable, ICollection input)
{

}
Pondidum
  • 11,457
  • 8
  • 50
  • 69
  • You can use [the same trick as for declaring a member variable](http://stackoverflow.com/a/4940249/429091), though this approach requires implementing classes to opt into the pattern. – binki Aug 07 '16 at 16:05

4 Answers4

59

You can:

1) Define an interface that inherits both required interfaces:

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

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

2) Use generics:

private void DoSomething<T>(T input)
    where T : IComparable, ICollection
{...}
Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
  • 3
    in VB.Net: Private Sub DoSomthing(Of T As {IComparable, ICollection })(ByVal input As T) ... End Sub – Pondidum Apr 21 '09 at 11:16
  • Is there a gain using one of these solutions over having two seperate parameters? Intuitively it seems like it would be useful, but I'm struggling to think of a concrete example. – CurtainDog Apr 21 '09 at 11:22
  • 1
    I cannot think of one at the moment, but I did want to do this few days ago. and having one parameter looks better than calling DoSomthing(testData,testData) and thus passing the same instance in twice. – Pondidum Apr 21 '09 at 11:37
  • 10
    1) only works if you can change ALL the classes that implements both interfaces to implement the new interface. 2) I like the generic route – Ian Ringrose Nov 04 '09 at 11:24
6

You can inherit another interface from those two interfaces and make your parameter implement that interface.

Steve Willcock
  • 26,111
  • 4
  • 43
  • 40
3

Well, yes, and no.

You can, as Steve has suggested, create another, third, interface which descends from the two you want, and use that for the parameter type.

However, this will also make it a requirement that the class being used implements that third interface as well.

In other words, this won't work:

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

However, you can trick the compiler into what you want by way of generics.

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

Now it will work. I'm still not 100% sure that won't give you other issues though, I'd have to think about it.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
2

The generic function approach mentioned above is a good one, with one big caveat: in order to typecast an object so that it can be passed to a routine with multiple generic constraints, one must know a type which meets those constraints and is a parent type of the object being cast. A routine that accepts such an object will know such a type (it was passed in as a generic type parameter) but there's no nice way for a class to persist such information and use it later. If a variety of unrelated types implement both IFoo and IBar, it would be difficult to design a routine which could accept a number of unrelated object instances, store them in a list or something, and then pass all the items in the list to a routine with a generic IFoo+IBar parameter.

If such a scenario might be necessary, the best approach would be to have a non-generic counterpart for each generic routine which would accept e.g. a parameter of type IFoo and cast it to an IBar as needed. One could then store all the items in a List<IFoo> and pass them to the routine. One would lose the type-safety of the generic method, but sometimes perfect type-safety isn't achievable.

supercat
  • 77,689
  • 9
  • 166
  • 211