// EXAMPLE 5 ----------------------------------------
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
MathProvider<int>.Sum(new int[] { 1, 2, 3, 4, 5});
}
}
public static class MathProvider<T>
{
public static T Sum(T[] array)
{ // (1) still requires a custom implementation for every type
if (typeof(T) == typeof(int))
{
T sum = (T)(object)0; // (2) largescale casting is very glitch prone
for (int i = 0; i < array.Length; i++)
sum = (T)(object)((int)(object)sum + ((int)(object)array[i]));
return sum; } t
hrow new System.Exception("UNSUPPORTED TYPE"); // (3) runtime errors
} } }
// (4) horribly slow...
事实是,这看起来要比接口化方法好。代码很简单并且容易使用。然而,和以前一样我们还是有很多问题:
我们仍要为每一种类型创建一个定制的实现。
同时我们有大量的类型转换可能造成异常而且很慢。
以及对不支持的类型有运行时错误。
性能低下。
注:我不知道他们是否仍然在用 F# 来做这个,但是当我浏览 F# 中一般的标准数学函数时,他们所做的看起来像是最低水平的对象转换。可笑至极!
对象转换是另一个死胡同,但它至少非常简单易用。
代理
代理......真的很棒!
我们不能像使用原始类型那样高效地完成数学运算。如果没有每种继承关系编译器将不能作出判断,并且我们也不能让C#的原始类型继承我们自己的类。
所以,我们把一般类外的一般代码的功能都移除吧。我们需要怎么做呢?代理!只要在一般的类里设置一个代理,并在运行时从外部分配,这些类型就能够被编译器所识别。
然而,我们可以把委托(代理)放到泛型类中,在外部编译委托(代理)然后在运行时分配。
Hide Shrink Copy Code
// EXAMPLE 5 ----------------------------------------
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{ // (1) requires a constructor method to be called prior to use
MathProviderConstructors.Construct();
MathProvider<int>.Sum(new int[] { 1, 2, 3, 4, 5});
} }
public static class MathProviderConstructors
{
public static void Construct()
{
// (2) still requires a custom implementation for every type
MathProvider<int>.Sum = (int[] array) =>
{
int sum = 0;
for (int i = 0; i < array.Length; i++)
sum = sum + array[i];
return sum;
}; } }
public static class MathProvider<T>
{
// (3) still have runtime errors for non-implemented types (null-ref)
public static System.Func<T[], T> Sum;
} }
EXMAPLE 5 是目前最好的泛函例子。它运行很快,适用于任何类型,并且除了要确保静态构造方法必须被调用外很容易使用。但是,它仍有一些瑕疵...(1)构造方法必须被调用,(2)对每一个类型依旧须要自定义一个实现,(3)还会抛出运行时错误。