C#中的泛型与C++中的模板
2013-10-22 23:23
288 查看
今天一个同事问我C#中有没有模板函数,他想写一个函数能够处理不同的类型,里面算法一样,如果要重载实现的话,就造成大量重复的代码,而且扩展性不好。我说肯定有啊,你可以上网搜一下,结果他说没搜到,而我对C#根本就不熟,我就和他说你先按照重载的方式先做着,我再查查。
晚上回家之后,拿了本C#的书翻了一下,一下就找到了,就是C#泛型,我猜同事肯定搜的”模板“,所以没搜到。下面记录一下C#的泛型和C++中的模板不同之处:
1,声明方式
C#中的泛型声明方式为,在标识符后面直接加<T>即可,而C++需要使用template关键字,如下:
C#:
class Stack<T>
{
public void Push(T name);
......
};
C++:
template <class T>
class Stack
{
public:
void Push(T name);
};
从上面的两种写法可以看出,显然C#要更简单一些。
上面这是类的泛型化,对于函数的泛型,也类似,如下:
C#:
void Func<T>(T name);
C++:
template <class T>
void Func(T name);
2,泛型约束
C#的泛型比C++模板增加了一个泛型参数约束功能,这在某些场景下非常有用,它可以限制某个泛型参数的使用范围,例如我们可以约束泛型类型Shop<T>的参数只能为Customer类或其子类。如果我们这么写:
那么var cust = (Customer)customer;这句话将编译错误,C#无法进行类型转换,因为对于类型参数T,C#在编译期间根本知道它是什么类型,所以无法进行转换,但是如果对T做个限制,结果会怎么样呢,先看看C#中泛型约束的语法:
class Shop<T> where T: Customer
很简单,就是增加一个where子句,约束的类型如果有多个可以用逗号隔开,如下:
class Shop<T> where T: class, ICustomer, new()
如果类型参数有多个,则写多个where,如下:
class Shop<T1, T2> where T1:Customer where T2:Superman
这里要注意的是C#的泛型约束是有很多要求的,约束类型只有6种,如下:
class:类型实参必须是引用类型;
struct:类型实参必须是值类型;
<base class name>:类型实参必须是指定的类或者其派生类;
<interface name>:类型实参必须是指定的接口类,或其派生类
new():类型实参必须有一个无参数的公共构造函数;
U:类型实参T必须是另一个类型实参U或者U的派生类。
而且where子句内部的约束类型是有顺序要求的,首先class,struct,<base class name>必须只能取其中一个,且只能放在最前面,之后是<interface name>,这个可以是多个,而new()必须放在最后,向int,string这些 密封类则不能作为约束参数的。
所以上面的语句如果写成如下,就不会有错了,而且VS的IntelliSense会非常智能地弹出customer的成员,如下:
其他关于C++的模板和C#的泛型使用上基本一样,除了C#特有的一些功能,如委托泛型,接口泛型等。
对了,其实我同事那个问题用object做函数的参数也是可以实现的,但是执行效率比泛型要低。
晚上回家之后,拿了本C#的书翻了一下,一下就找到了,就是C#泛型,我猜同事肯定搜的”模板“,所以没搜到。下面记录一下C#的泛型和C++中的模板不同之处:
1,声明方式
C#中的泛型声明方式为,在标识符后面直接加<T>即可,而C++需要使用template关键字,如下:
C#:
class Stack<T>
{
public void Push(T name);
......
};
C++:
template <class T>
class Stack
{
public:
void Push(T name);
};
从上面的两种写法可以看出,显然C#要更简单一些。
上面这是类的泛型化,对于函数的泛型,也类似,如下:
C#:
void Func<T>(T name);
C++:
template <class T>
void Func(T name);
2,泛型约束
C#的泛型比C++模板增加了一个泛型参数约束功能,这在某些场景下非常有用,它可以限制某个泛型参数的使用范围,例如我们可以约束泛型类型Shop<T>的参数只能为Customer类或其子类。如果我们这么写:
class Customer { public string Name{get;set;}; public string CreditCardNo{get;set;}; } class Shop<T> { public void Print(T customer) { var cust = (Customer)customer; Console.WriteLine(cust.Name); ............ } }
那么var cust = (Customer)customer;这句话将编译错误,C#无法进行类型转换,因为对于类型参数T,C#在编译期间根本知道它是什么类型,所以无法进行转换,但是如果对T做个限制,结果会怎么样呢,先看看C#中泛型约束的语法:
class Shop<T> where T: Customer
很简单,就是增加一个where子句,约束的类型如果有多个可以用逗号隔开,如下:
class Shop<T> where T: class, ICustomer, new()
如果类型参数有多个,则写多个where,如下:
class Shop<T1, T2> where T1:Customer where T2:Superman
这里要注意的是C#的泛型约束是有很多要求的,约束类型只有6种,如下:
class:类型实参必须是引用类型;
struct:类型实参必须是值类型;
<base class name>:类型实参必须是指定的类或者其派生类;
<interface name>:类型实参必须是指定的接口类,或其派生类
new():类型实参必须有一个无参数的公共构造函数;
U:类型实参T必须是另一个类型实参U或者U的派生类。
而且where子句内部的约束类型是有顺序要求的,首先class,struct,<base class name>必须只能取其中一个,且只能放在最前面,之后是<interface name>,这个可以是多个,而new()必须放在最后,向int,string这些 密封类则不能作为约束参数的。
所以上面的语句如果写成如下,就不会有错了,而且VS的IntelliSense会非常智能地弹出customer的成员,如下:
class Customer { public string Name{get;set;}; public string CreditCardNo{get;set;}; } class Shop<T> { public void Print(T customer) { Console.WriteLine(customer.Name); } }
其他关于C++的模板和C#的泛型使用上基本一样,除了C#特有的一些功能,如委托泛型,接口泛型等。
对了,其实我同事那个问题用object做函数的参数也是可以实现的,但是执行效率比泛型要低。
相关文章推荐
- C++ 模板和 C# 泛型之间的区别
- C++ 模板和 C# 泛型之间的区别(C# 编程指南)
- C++与C#对比学习:模板,泛型
- C#/C++ 模板和 C# 泛型之间的区别(C# 编程指南
- C++ 模板和 C# 泛型之间的区别(C# 编程)
- C# 泛型和 C++ 模板
- C#中的静态构造函数 静态类 C# 泛型和 C++ 模板之间的主要差异
- C#和Java的泛型、C++模板、C#的constraints特性以及弱类型化和强类型化的问题(转)
- C++、C#、JAVA中模板与泛型
- C++ 模板和 C# 泛型之间的区别
- JAVA的泛型和C++的模板的区别与联系
- C#模板编程(1):有了泛型,为什么还需要模板?
- C++ 泛型程序设计 模板
- JAVA的泛型和C++的模板的区别与联系
- (原創) 我的Design Pattern之旅[7]:使用泛型改進Adapter Pattern (OO) (Design Pattern) (C/C++) (template) (.NET) (C#) (C++/CLI) (VB)
- C++泛型与模板
- C++ Coding Standards:模板和泛型
- (原創) 如何讓泛型支援多個interface? (.NET) (C/C++) (C#) (template) (C++/CLI)
- JAVA C# C/C++比教学:泛型
- Anders Hejlsberg谈C#、Java和C++中的泛型