I'm a beginner with C# and can't find any answer for this :
Im trying to delegate Actions with some interface parameter , but push through functions with objects that extend this interface (or class)
// some class extending interface
public class IntEvent : IFace{}
public class MoveEvent : IFace{}
// function i like to use to verify Action
static void setAction(Action<IFace> evt) {
// evt ...
}
// function to delegate as Action
static void evtCheck(IntEvent evt) {
// some func
}
static void evtMove(MoveEvent evt) {
// some func
}
// class {
// call method inside class and delegate this function :
setAction(evtCheck);
setAction(evtMove);
I'm receiving an error that "evtCheck(IntEvent)
cannot be converted to Action<IFace>
" , even if IntEvent
extends the IFace
interface .
How should I solve this ? Maybe I have to use Func or Delegate ?
Interface delegation, in Kotlin, is a simple yet powerful technique that allows a class to delegate the actual implementation of the interfaces, to separate objects.
Interface can be inherited and implemented by any class and a Delegate can be created for a method on any class, as long as the method suits the method signature of the delegate.
You can initialize an Action delegate using the new keyword or by directly assigning a method: Action<int> printActionDel = ConsolePrint; //Or Action<int> printActionDel = new Action<int>(ConsolePrint); An Action delegate can take up to 16 input parameters of different types.
It contains both methods and properties. It can be applied to one method at a time. If a class implements an interface, then it will implement all the methods related to that interface. If a delegate available in your scope you can use it.
You can't do what you're trying to do - you're expecting covariance, but Action<T>
is contravariant on its only type-parameter.
You can't do a method-group conversion from evtCheck
to Action<IFace>
because evtCheck
needs a more specific type (IntEvent
) as its argument than the more general IFace
type that an Action<IFace>
instance expects. If such a conversion were allowed, what would you expect to happen if the delegate were executed with an argument that implements IFace
but is not an IntEvent
?
I think you should have another look at your design because it looks like there's a flaw there, but if you want, you can create a lambda to force a cast of the argument to the desired type and accept the possibility of an InvalidCastException
:
setAction(iFace => evtCheck((IntEvent)iface));
More likely, you might want to make evtCheck
accept a more general type or setAction
to accept a more specific delegate.
Action<T>
is contravariant in T, so methods taking an Action<T>
will also accept Action<U>
where T is derived from U.
Your IntEvent
class, however, implements the IFace
interface, which means that if the compiler accepted your setAction()
call, it would be possible to call evtCheck()
with an argument that is another IFace
-derivative and not IntEvent
, a runtime error and a clear violation of type safety.
Obligatory Eric Lippert reference: Covariance and contravariance
EDIT: from your description it seems to me that what you really want is differentiation based on the method parameter's type, so e.g. you want a separate action for IntEvent
, another one for (a hypothetical) DoubleEvent
etc. If this is the case, you are actually after double virtual dispatch, which is not directly supported in C#, but you can simulate it using the Visitor design pattern.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With