Sorry...I thought the various answers explained pretty well why you don't want to do this. Even though you think you do (a common enough mistake, so no reason to feel badly about it). It didn't occur to me that after reading all of those questions and their answers, you wouldn't feel you had an adequate answer to your own question. I'm not sure I can add much to them, but I'll try…
The short version: if you were allowed to add an instance of Func<MyType<ConcreteType>, bool>
to a list of Func<IMyType, bool>
, then some other code could pull that instance out as a Func<IMyType, bool>
and then try to call it, passing to the delegate an instance of IMyType
other than MyType<ConcreteType>
.
But, your method (presumably, given the delegate declaration) expects only instances of MyType<ConcreteType>
! What would it do if it were passed some other implementation of IMyType
?
The compiler tried to help prevent you from making that mistake, when it gave you the compile-time error at list.Add(func)
. You hid the error from the compiler with the cast, but that doesn't change the fundamental hazard the compiler is trying to save you from, and so the run-time has to step in when you attempt the cast and stop you there.
It would have been better to block the code at compile-time, but that's not possible when you use a cast to claim you know something about the type that the compiler doesn't. But it's still better to get the run-time error there at the cast, rather than later when you try to pass some other implementation of IMyType
to the method the delegate represents.
Now, the code example you've given doesn't make very clear why you think this would even be advantageous to do. So it's impossible to know what alternative would be best in your case.
If the method the delegate reference does indeed need to know the type is MyType<ConcreteType>
, then you're stuck. It simply is not safe to put a delegate referencing that method in a context where any IMyType
could get passed to it. You painted yourself into a corner somehow, and you need to rethink your design, because it currently has a fundamental flaw in it.
Note, however, that if you really only use the IMyType
-ness of the object in your method, then the solution is to just declare it that way. For example, the lambda expression you show would compile just fine if assigned instead to a variable of type Func<IMyType, bool>
, which you could add to the list.
Alternatively, if you are 100% certain that no code will ever attempt to invoke the delegate with an implementation of IMyType
other than MyType<ConcreteType>
, you could wrap the wrong delegate type in an instance of the right delegate type. For example:
list.Add(o => func((MyType<ConcreteType>)o));
Of course, by doing that you will completely remove the bulk of the type-safety features of using the generic List<T>
object. It definitely has that "bad code smell" to it. But it would compile, and would even run as long as you never break the rules and try to invoke the delegate with a different implementation of IMyType
.