博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用dynamic增强C#泛型表达力
阅读量:6679 次
发布时间:2019-06-25

本文共 1194 字,大约阅读时间需要 3 分钟。

C++的泛型是基于模板(template)技术的。模板本身并不作为独立的编译单元,而是在编译时绑定实际参数类型进行模板实例化,类似于C语言的宏展开,在运行时并不存在独立的模板类型。模板对泛型参数的约束是基于操作的语法特征的,属于一种静态的duck typing机制,十分灵活。

下面的代码定义了一个泛型Add函数,它对泛型参数T的要求只是支持+运算,并不要求T是某个类的子类,或是实现了某个接口。int, double, std::string等支持+运算符的类型都可以成功匹配T。

//C++

template<typename T>

T Add(const T& t1, const T& t2) {
    return t1 + t2;
}

int main() {

    int i = Add(1, 2);
    double d = Add(1.1, 2.2);
    std::string s = Add(std::string("abc"), std::string("def"));

    std::cout << i << " " << d << " " << s << std::endl;

    return 0;

}

 

输出:

>>3 3.3 abcdef

 

而类似的代码在C#中却无法编译通过:

 

这是由于C#采用基于reification的泛型机制,泛型类会单独编译,并且在运行时存在;因此,C#对于泛型参数的要求更加严格,只能通过where关键字表达基于继承关系的约束,无法通过duck typing的方式表达类型约束。与模板相比,这种机制的好处在于可以更好的支持反射和元编程,但其缺点是泛型的表达能力不如模板。幸好C#4.0中引入了动态类型机制,我们可以通过动态类型来实现基于duck typing的泛型参数约束。

//C#

static class Calculator {

    public static T Add<T>(T t1, T t2) {
        dynamic d1 = t1;
        dynamic d2 = t2;

        return (T)(d1 + d2);

    }
}

public static void Main(string[] args){

    int i = Calculator.Add(1, 2);
    double d = Calculator.Add(1.1, 2.2);
    string s = Calculator.Add("abc", "def");

    Console.WriteLine(i + " " + d + " " + s);

}

 

输出:

>>3 3.3 abcdef

 

除了运算符重载,对于普通的方法调用也是适用的。这种方法是一种动态duck typing的泛型参数约束机制,依赖于运行时的方法查找,与模板编译时的检查不同,它需要使用者保证传入的对象符合相应要求。

 

参考:

转载地址:http://fmnao.baihongyu.com/

你可能感兴趣的文章
php数据类型以及运算
查看>>
npm命令
查看>>
关于实现(大)系统的一些小体会
查看>>
如何使用github创建仓库并且与本地连接
查看>>
除法(简单枚举)
查看>>
System.Web.Caching
查看>>
linux常用命令 2
查看>>
jquery中prop和attr的区别
查看>>
2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) Problem K Tournament Wins
查看>>
台州学院we are without brain 训练 计算几何
查看>>
Webpack 代码分离
查看>>
ssh下:系统初始化实现ServletContextListener接口时,获取spring中数据层对象无效的问题...
查看>>
extundelete
查看>>
powerviot install in sharepoint 2013
查看>>
javascript在我的工作的用法
查看>>
《告诉他们,我已乘白鹤去了》观后感——用生命换取信仰
查看>>
诡秘的“端口安全”功能
查看>>
为VMware ESXi主机添加本地存储的过程及注意事项-之4
查看>>
oracle 11g 客户端安装检查过程中报物理内存不足的解决
查看>>
nagios中自己写的监控mysql主从复制的插件
查看>>