EventHandlers and covariance

I am trying to create a common event. Basically it should look like this:

namespace DelegateTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var lol = new SomeClass();
            lol.SomeEvent += handler;
        }

        static void handler(object sender, SomeDerivedClass e)
        {

        }

    }

    class SomeClass
    {

        public delegate void SomeEventDelegate<in T>(object sender, T data);
        public event SomeEventDelegate<ISomeInterface> SomeEvent;

    }

    interface ISomeInterface
    {
    }

    class SomeDerivedClass : ISomeInterface
    {
    }
}

I want to allow the user to pass any delegate whose second parameter is derived from "ISomeInterface".

"in" indicates a contradiction, right? This means that if the API expects something more general, you can pass it something more specific (in my database, “ISomeInterface” would be common, and my “SomeDerivedClass” would be specific.) I, however, are told to my compiler that "no overload for the method handler matches DelegateTest.SomeClass.SomeEventDelegate".

I am wondering why this is not working. What problems can be caused if this is so? Or am I missing something for this?

Thanks in advance!

+5
2

"in" contra-variance, ?

.

, API , - ( "ISomeInterface" , "SomeDerivedClass" ).

. - , , . , , ISomeInterface :

interface ISomeBaseInterface
{
}

interface ISomeInterface : ISomeBaseInterface
{
}

handler ISomeBaseInterface SomeDerivedClass:

static void handler(object sender, ISomeBaseInterface e) 

new SomeClass().SomeEvent += handler .

: SomeClass SomeEvent, -, ISomeInterface data. , SomeDerivedClass,

class SomeOtherDerivedClass : ISomeInterface
{
}

void handler(object sender, SomeDerivedClass e) , SomeOtherDerivedClass, .

, , , , , .

: :

, . , let say SomeOtherDerivedObject, , , , (object, SomeOtherDerivedObject). , , .

, # event, . , :

class SomeClass
{
    private Delegate handlers;

    public delegate void SomeEventDelegate<in T>(object sender, T data);

    public void AddSomeEventHandler<T>(SomeEventDelegate<T> handler)
    {
        this.handlers = Delegate.Combine(this.handlers, handler);
    }

    protected void OnSomeEvent<T>(T data)
    {
        if (this.handlers != null)
        {
            foreach (SomeEventDelegate<T> handler in
                this.handlers.GetInvocationList().OfType<SomeEventDelegate<T>>())
            {
                handler(this, data);
            }
        }
    }
}
+6

, , eg. Action<Fruit> , Action<Banana>, , Action<Fruit> Action<Banana> *, Action<Banana>. , :

    static T As<T>(this Delegate del) where T : class
    {
        if (del == null || del.GetType() == typeof(T)) return (T)(Object)del;
        Delegate[] invList = ((Delegate)(Object)del).GetInvocationList();
        for (int i = 0; i < invList.Length; i++)
            if (invList[i].GetType() != typeof(T))
                invList[i] = Delegate.CreateDelegate(typeof(T), invList[i].Target, invList[i].Method);
        return (T)(Object)Delegate.Combine(invList);
    }

, , ; , , . , , , , , , . , , Action<string>, , . Action<object> "" Action<string> .

- , Intellisense, :

    static void AppendTo<T>(this Delegate newDel, ref T baseDel) where T : class
    {
        newDel = (Delegate)(Object)newDel.As<T>();
        T oldBaseDel, newBaseDel;
        do
        {
            oldBaseDel = baseDel;
            newBaseDel = (T)(Object)Delegate.Combine((Delegate)(object)oldBaseDel, newDel);
        } while (System.Threading.Interlocked.CompareExchange(ref baseDel, newBaseDel, oldBaseDel) != oldBaseDel);
    }

    static void SubtractFrom<T>(this Delegate newDel, ref T baseDel) where T : class
    {
        newDel = (Delegate)(Object)newDel.As<T>();
        T oldBaseDel, newBaseDel;
        do
        {
            oldBaseDel = baseDel;
            newBaseDel = (T)(Object)Delegate.Remove((Delegate)(object)oldBaseDel, newDel);
        } while (System.Threading.Interlocked.CompareExchange(ref baseDel, newBaseDel, oldBaseDel) != oldBaseDel);
    }

, Delegate, ; - , / .

+2

All Articles