关于带泛型约束的虚函数在托管函数中的调用问题
2012-10-10 13:23
274 查看
新编辑内容(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 {
static void Main(string[] args)
{
SubClass sub = new SubClass();
sub.CallFunc();
Console.ReadKey();
}
}
public abstract class SuperClass
{
public virtual void Func<TEntity>()
where TEntity : class
{
Console.WriteLine("super class's function");
}
public void NonVirtualFunc<TEntity>()
where TEntity : class
{
Console.WriteLine("super class's none virtual function");
}
}
public class SubClass : SuperClass
{
public delegate void Caller();
////这里覆盖父类的虚方法,但是下面用不同的调用方式调用,实际测试结果为有没有这个覆盖方法效果都一样,该异常的地方还是异常
public override void Func<TEntity>()
{
base.Func<TEntity>();
}
public void CallFunc()
{
//这里采用普通方式调用父类的虚方法Func
base.Func<string>();
//这里使用一个代理来调用父类的虚方法Func,注意这里子类并没有覆写父类的Func方法
Action action = new Action(() =>
{
base.NonVirtualFunc<string>();//不会出现异常
this.Func<string>();//不会出现异常
base.Func<string>();//出现异常
});
action();
//另外一种托管调用方式,效果和上面通过Action调用一样
Caller caller = () =>
{
base.NonVirtualFunc<string>();
base.Func<string>();
};
caller();
}
}
}
就上面这个问题,查询了大量的资料,都没有找到原因,谁能解答一下呢?
根据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 {
static void Main(string[] args)
{
SubClass sub = new SubClass();
sub.CallFunc();
Console.ReadKey();
}
}
public abstract class SuperClass
{
public virtual void Func<TEntity>()
where TEntity : class
{
Console.WriteLine("super class's function");
}
public void NonVirtualFunc<TEntity>()
where TEntity : class
{
Console.WriteLine("super class's none virtual function");
}
}
public class SubClass : SuperClass
{
public delegate void Caller();
////这里覆盖父类的虚方法,但是下面用不同的调用方式调用,实际测试结果为有没有这个覆盖方法效果都一样,该异常的地方还是异常
public override void Func<TEntity>()
{
base.Func<TEntity>();
}
public void CallFunc()
{
//这里采用普通方式调用父类的虚方法Func
base.Func<string>();
//这里使用一个代理来调用父类的虚方法Func,注意这里子类并没有覆写父类的Func方法
Action action = new Action(() =>
{
base.NonVirtualFunc<string>();//不会出现异常
this.Func<string>();//不会出现异常
base.Func<string>();//出现异常
});
action();
//另外一种托管调用方式,效果和上面通过Action调用一样
Caller caller = () =>
{
base.NonVirtualFunc<string>();
base.Func<string>();
};
caller();
}
}
}
就上面这个问题,查询了大量的资料,都没有找到原因,谁能解答一下呢?
相关文章推荐
- 关于,函数调用是传值调用,初始化函数中重新分配内存,导致形参的值和实参的值不一致 问题分析
- 关于在C#中构造函数中调用虚函数的问题
- 由Point p1 = p和p1 = p的区别想到的关于copy构造函数和赋值操作符重载函数的调用时机问题
- C++笔试题 关于函数析构函数未调用的问题
- 关于VC中LineDDA函数的调用问题
- 关于类成员函数指针的调用问题
- 关于函数内部调用全局变量的问题
- 关于C51的中断函数要注意的几个问题 -----中断中调用函数参数错误问题
- C++关于参数为const引用类型的函数调用参数成员函数的一个问题
- C#关于静态函数与普通函数之间的调用问题,以及可变参数的使用
- 关于调用MFC CHttpFile Seek函数抛异常的问题
- 关于Qt调用多个.m文件形成的函数问题。
- vim: 关于 Decho 命令不支持静态变量问题 ?,改为函数调用可行。
- 关于javascript基于DWR调用java函数的传值问题
- 关于调用js函数失败问题及解决
- Qt-QML-关于两个平级的qml文件中的函数调用问题
- C/C++中关于函数调用结束后变量释放的问题
- 关于函数调用的loop的一个问题
- 关于在C/C++语言中,函数如何返回数组,数组如何作为参数传递以及返回数组的函数该如何调用问题的总结
- 关于函数调用过程中的实参和形参问题