The following code shows what I would like to do; that is, I would like to constrain anObject, so that it can be used as a parameter to various methods with use IInterfaceOne or IInterfaceTwo, where neither inherits from the other.
public interface IInterfaceOne { }
public interface IInterfaceTwo { }
public class Implementation : IInterfaceOne, IInterfaceTwo
{
}
public interface IInterfaceOneAndTwo : IInterfaceOne, IInterfaceTwo { }
public class UsingImplementation
{
IInterfaceOneAndTwo anObject = (IInterfaceOneAndTwo)(new Implementation()); //fails because Implementation doesnt acctually implement IInterfaceOneAndTwo
}
This example fails however as IInterfaceOneAndTwo is an interface in its own right, and Implementation does not implement it.
I know if I used generics I could constrain them, but I am wondering, if there is a way to do this without generics?
Is there a way to say anObject shall implement IInterfaceOne and IInterfaceTwo, without using IInterfaceOneAndTwo?
“Incoming” generic class parameters and generic method parameters can combine types, but there is no facility for variables or fields to represent “composite” types. Further, in order to pass an object to a parameter of a generic type which combines multiple constraints, the object must be cast to a type which in fact implements all of those constraints. This can be difficult.
For example, suppose class
FooandBarboth implementIntf1andIntf2. One wishes to write a functionAddToList<T>(thing as T) where T:Intf1,Intf2. Such a function will perfectly happily accept objects of typeFooorBar. Suppose, however, one wishes to use such a function to add all objects to the same list (which might be a mix ofFoo,Bar, and any number of other types that also happen to implementIntf1andIntf2) and then later pass those objects to a function whose parameter is likewise constrained to implement bothIntf1andIntf2. One could cast toFooany object which happened to be aFoo, and cast toBarany object which happened to be aBar, but if other types are written which also handleIntf1andIntf2, it would be difficult to deal with them.It is possible to solve the problem, somewhat awkwardly, without using Reflection or other such tricks. Define an interface
IActUpon<Base1, Base2>with a methodActUpon<thingType>ActUpon(thingType thing) where thingType: Base1, Base2. Implementations of such a method will be able to pass parameterthingto other methods requiring generic method parameter constrained toBase1andBase2. The biggest difficulties with such an approach are that one must write separate code for each possible number of constraints, and that in many places where one would have used a lambda expression one will instead have to write an implementation ofIActUpon....