今天微软的一个Developer给我们做了三个讲座,其中谈到了C# 2.0中的新特性。因为我对C++中的Generic Programming比较熟,因此在他讲的时候就想到了几个问题。
C# 1.0中是不支持方法参数的默认值的,这只能通过overload来模拟支持。同样,C# 2.0的Generic class中,相信也不会提供模板参数的默认值的功能。而在C++中,提供模板参数默认值是非常常见的,并且能够帮助Client更为简单的调用Generic class,例如C++ STL中的set:
C# 2.0中要想提供这样的便利,至于要支持两个特性:模板参数默认值和previous模板参数的引用。不同于方法参数的默认值,模板参数的默认值,尤其是基于previous参数的默认值,是很难模拟的。
除了默认参数,还不清楚C# 2.0中否支持non-type的模板参数,从目前的资料来看是不支持的,按照现有的语法都不容易添加这一功能。
C# 2.0中提供了一个关键词where, 用于Generic参数的限制,比如限制必须实现特定接口等。
C++中的Full specialization和partial specialization在C# 2.0中似乎也不支持,这对于C++中形成的traits, meta-programming等思想就不能很好的在C# 2.0中应用。不过与C++区别比较大的是,C#中所有的方法都必须定义在类中,因此对于方法来说,specialization也有代替的方案,那就是overload。
比如如下代码:
如果在Client调用NormalTest.Foo(1),输出会为"two",也就是说,C# 2.0优先选择more specialized的重载,只有所有Specialized的重载都不符合后,才会使用Generic的版本。注意这种Overload的Resolve是不考虑modifier的保护级别的,如果将NormalTest.Foo(int)的public变成private,调用NormalTest.Foo(1)的代码在编译时就会发生一个错误,编译器认为从类外调用了一个private的方法。
对于GenericTest的情况,如果从其某一个静态方法内调用Foo(1),我想应该是Foo(int)这个方法被调用,但如果在类外以GenericTest<int>.Foo(1)的方式调用,我还不清楚是输出"one", "two"还是编译出错。因为我现在的机器没有装.NET 2.0 beta,所以无法验证,有装.NET 2.0 beta的可以试一下。还有,调用NormalTest.Foo<int>(1)时会有什么输出,也需要验证。单纯的猜测是靠不住的。
因为C# 2.0中提供了Partial Type,因此在多个文件中提供类中某一个Generic Method的specialized版本,应当是比较有效的。总体感觉C# 2.0实现的Generic虽然有限,但也算得上是一个完备的功能集,用起来还是很方便的。
很久以前看到C# 2.0的一些介绍,已经好久没有关注了,只因为今天的讲座想起了这些,欢迎大家与我讨论交流。