I have three marker interfaces for a fluent API's extension methods:
interface IOne { }
interface ITwo { }
interface IOneOrTwo : IOne, ITwo { }
and the following extension method:
public static IOneOrTwo Foo (this IOne obj, string arg)
{
// do something with arg
return obj; // <- possible without cast?
}
Question: is it somehow possible to return obj without casting? Normally you need to explicitly downcast in this situation, however, none of those interfaces is requiring the underlying object to have any sort of method/property/whatsoever.
Note: The actual implementation class implements all of the interfaces.
Question 2: Why is implementing IOne
and ITwo
not automatically let the implementation be also of type IOneOrTwo
?
is it somehow possible to return obj without casting?
No. Just because a class implements IOne
does NOT mean it also implements IOneOrTwo
. So you need to cast (which may well fail)
none of those interfaces is requiring the underlying object to have any sort of method/property/whatsoever.
That's irrelevant. The lack of actual methods does not magically let you down-cast. If an object implements IOne
, technically it could implement IOneOrTwo
without adding any methods, but it still would need to explicitly include that in the class definition.
Why is implementing
IOne
andITwo
not automatically let the implementation be also of typeIOneOrTwo
Because IOneOrTwo
could include methods that are not part of IOne
or ITwo
. Just because an object implements IOne
and ITwo
does not mean it also implements any interface that also includes those two.
You could get what you want using generics:
public static T Foo<T> (this T obj, string arg) where T: IOne
{
// do something with arg
return obj;
}
then you could say:
IOneOrTwo obj = new IOneOrTwoImpl();
IOneOrTwo obj2 = obj.Foo("gfgfd"); // valid since obj implements IOneOrTwo
but you can't do:
IOne obj = new IOneImpl();
IOneOrTwo obj2 = obj.Foo("gfgfd"); // not valid since obj does not implement IOneOrTwo
without a cast.
Bottom line - interface implementations must be explicitly declared. Just because a class can implement an interface (meaning it contains all of the methods/properties that make up that interface) doesn't mean you can treat it as if it does implement that interface.