none
关于委托怎么匹配的问题,以及逆变和协变 RRS feed

  • 问题

  • 看了一下msdn里面关于逆变和协变的章节,在委托 那一章里面又一个疑问

    代码如下:

    public class First { }
    public class Second : First { }
    public delegate First SampleDelegate(Second a);
    public delegate R SampleGenericDelegate<A, R>(A a);
    
    
    // Matching signature.
    public static First ASecondRFirst(Second first)
    { return new First(); }
    
    // The return type is more derived.
    public static Second ASecondRSecond(Second second)
    { return new Second(); }
    
    // The argument type is less derived.
    public static First AFirstRFirst(First first)
    { return new First(); }
    
    // The return type is more derived 
    // and the argument type is less derived.
    public static Second AFirstRSecond(First first)
    { return new Second(); }
    // Assigning a method with a matching signature 
    // to a non-generic delegate. No conversion is necessary.
    SampleDelegate dNonGeneric = ASecondRFirst;
    // Assigning a method with a more derived return type 
    // and less derived argument type to a non-generic delegate.
    // The implicit conversion is used.
    SampleDelegate dNonGenericConversion = AFirstRSecond;    //         <-这一块有问题
    
    // Assigning a method with a matching signature to a generic delegate.
    // No conversion is necessary.
    SampleGenericDelegate<Second, First> dGeneric = ASecondRFirst;
    // Assigning a method with a more derived return type 
    // and less derived argument type to a generic delegate.
    // The implicit conversion is used.
    SampleGenericDelegate<Second, First> dGenericConversion = AFirstRSecond;
    
    

    如题那块上面的注释所说,分派了一个方法,它的返回值类型是原类型的derived輩,它的参数类型是是原类型的base輩。  然后发生了隐式转换和delegate相匹配。

    1.这是否是逆变和协变。如果是逆变和协变是否是默认可以的?因为子类转成父类可以理解(也就是协变),但是父类转为子类也可以吗?

    2.我尝试了一下其他的

    定义了委托和方法

    public delegate First FFDelegate(First f);

    public static Second RSecondASecond(Second s)

    { return new Second(); }

    public static First RFirstASecond(Second s)

    { return new First(); }

    public static Second RSecondAFirst(First f)

    { return new Second(); }

    发现

    FFDelegate FFssDele = RSecondASecond; //error报错,为什么呢,他不是会发生自动转换的吗?

    FFDelegate FFFSDele = RFirstASecond; //error

    FFDelegate FFSFDele = RSecondAFirst; //但是这个却成功了,难道是返回值可以自动转换,而参数不可以吗?

    2013年2月8日 14:32

答案

  • 委托必须是“参数”至少是同一类型,或者是其子类。但是究其本质还是存在协变和逆变的问题。

    简单来说——

    FFDelegateFFssDele=RSecondASecond;

    你在使用这个委托的时候肯定是:

    FFssDele(传入一个First类型的实体对象)。

    问题在于:Second继承于First,那么如果First还有其它子类呢(譬如说First还有一个Third的子类),

    你照样可以传送一个third实体进来,但是third和second毫无关系,你怎么把thrid转化成second(右边那个second的委托函数呢?)

    至于说第三个为什么可以,是因为它在语法上完全符合委托的参数,同时返回值也是First的子类,是可以相互转换。

    namespace CSharp
    {
        /// <summary>
        /// 保证父类K只能作为输入,不能用于输出;V只能输出,不能输入
        /// </summary>
        public delegate V MyDel<in K,out V>(K key)where K:V;
     
        class First
        {
        }
        class Second : First
        {
        }
     
        class Program
        {
            public static Second RSecondASecond(Second s) 
            { return new Second(); }
            public static First RFirstASecond(Second s) 
            { return new First(); }
            public static Second RSecondAFirst(First f)
            { return new Second(); }
     
            static void Main(string[] args)
            {
                MyDel<SecondFirst> f = new MyDel<SecondSecond>(RSecondASecond);
            }
     
        }
    }
    还可以参考:http://msdn.microsoft.com/zh-cn/library/ms173174(VS.80).aspx

    帮助一起改进论坛质量?提交你的意见于此。
    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    2013年2月9日 2:57
    版主