Co- and Contravariance bugs in .NET 4.0

前端 未结 4 1930
没有蜡笔的小新
没有蜡笔的小新 2020-12-08 06:54

Some strange behavior with the C# 4.0 co- and contravariance support:

using System;

class Program {
  static void Foo(object x) { }
  static void Main() {
          


        
4条回答
  •  庸人自扰
    2020-12-08 07:29

    This solution was originally posted by cdhowie for my question: Delegate conversion breaks equality and unables to disconnect from event but is appears to solve the problem of covariance and contravariance in context of multicast delegates.

    You first need a helper method:

    public static class DelegateExtensions
    {
        public static Delegate ConvertTo(this Delegate self, Type type)
        {
            if (type == null) { throw new ArgumentNullException("type"); }
            if (self == null) { return null; }
    
            if (self.GetType() == type)
                return self;
    
            return Delegate.Combine(
                self.GetInvocationList()
                    .Select(i => Delegate.CreateDelegate(type, i.Target, i.Method))
                    .ToArray());
        }
    
        public static T ConvertTo(this Delegate self)
        {
            return (T)(object)self.ConvertTo(typeof(T));
        }
    }
    

    When you have a delegate:

    public delegate MyEventHandler(T arg);
    

    You can use it while combining delegates simply by converting a delegate do desired type:

    MyEventHandler handler = null;
    handler += new MyEventHandler(c => Console.WriteLine(c)).ConvertTo>();
    handler += new MyEventHandler(c => Console.WriteLine(c)).ConvertTo>();
    
    handler(new MyClass());
    
    
    

    It supports also disconnecting from event the same way, by using ConvertTo() method. Unlike using some custom list of delegates, this solution provides thread safety out of the box.

    Complete code with some samples you can find here: http://ideone.com/O6YcdI

    提交回复
    热议问题