zoukankan      html  css  js  c++  java
  • 关于带泛型约束的虚函数在托管函数中的调用问题

    新编辑内容(2012-10-10 14:49:00)

    根据1楼朋友doylecnn的测试,我重新进行了尝试,发现是VS2012才有这个问题,估计是个BUG,看来新东西不能乱用啊。

    VS2010下正常,Mac里Mono下正常。跟操作系统没有关系。

    为啥VS2012会有这个问题呢?用的也是.NET 4没有用.NET 4.5。只是编译时一个采用VS2010一个采用VS2012,就有不同的结果?

    我已经上传了编译程序和源代码,感兴趣的可以下载玩玩。。。。。。 

    点击下载


    今天遇到个很奇怪的问题,我写了一个组件,要求传入一个Action对象,于是我同事调用时传入了一个匿名函数,如下:

    caller.Process(()=>{
        base.Delete<News>(id);
    }); 

    然后运行后出现异常:类型参数“TEntity”与类型参数“TEntity”的约束冲突。

    那么多年第一次遇到这种稀有问题,经过跟踪调试,发现这个问题出现的条件如下:

    1.要调用的方法必须是一个在父类当中的虚方法(virtual)。

    2.在子类中,必须通过一个托管函数来直接调用父类的base.Func()虚方法,如果子类进行了覆盖(override),然后在覆盖中使用base.Func()都没有问题。

    3.父类的这个虚方法是泛型 ,并且必须具备泛型约束,没有约束也不会出现问题。

    写了个简单的示例代码:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 
     6 namespace VirtualFunction
     7 {
     8     class Program
     9     {
    10         static void Main(string[] args)
    11         {
    12             SubClass sub = new SubClass();
    13             sub.CallFunc();
    14             Console.ReadKey();
    15         }
    16     }
    17 
    18     public abstract class SuperClass
    19     {
    20         public virtual void Func<TEntity>()
    21             where TEntity : class
    22         {
    23             Console.WriteLine("super class's function");
    24         }
    25 
    26         public void NonVirtualFunc<TEntity>()
    27             where TEntity : class
    28         {
    29             Console.WriteLine("super class's none virtual function");
    30         }
    31     }
    32 
    33     public class SubClass : SuperClass
    34     {
    35         public delegate void Caller();
    36 
    37         ////这里覆盖父类的虚方法,但是下面用不同的调用方式调用,实际测试结果为有没有这个覆盖方法效果都一样,该异常的地方还是异常
    38         public override void Func<TEntity>()
    39         {
    40             base.Func<TEntity>();
    41         }
    42 
    43         public void CallFunc()
    44         {
    45             //这里采用普通方式调用父类的虚方法Func
    46             base.Func<string>();
    47 
    48             //这里使用一个代理来调用父类的虚方法Func,注意这里子类并没有覆写父类的Func方法
    49             Action action = new Action(() =>
    50             {
    51                 base.NonVirtualFunc<string>();//不会出现异常
    52                 this.Func<string>();//不会出现异常
    53                 base.Func<string>();//出现异常
    54             });
    55             action();
    56 
    57             //另外一种托管调用方式,效果和上面通过Action调用一样
    58             Caller caller = () =>
    59             {
    60                 base.NonVirtualFunc<string>();
    61                 base.Func<string>();
    62             };
    63             caller();
    64         }
    65     }
    66 }

    就上面这个问题,查询了大量的资料,都没有找到原因,谁能解答一下呢? 

  • 相关阅读:
    SQL 数据库中将某表中的一列数据拆分作为查询条件
    SQL数据库导入数据时提示未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序。 (System.Data)
    SQL常用内置函数
    SQL常用语句
    关于网页中鼠标双击文字选中设置
    SQL数据库查询列的类型及长度
    ASP. NET MVC项目 使用iTextSharp将网页代码生成PDF文件
    eslint-config-airbnb vs prettier vs standard
    windows批处理(bat脚本)
    python日志库loguru
  • 原文地址:https://www.cnblogs.com/sweetwxh/p/2718148.html
Copyright © 2011-2022 走看看