C# 中利用运行时编译实现泛函(3)

// 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)还会抛出运行时错误。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/44fd2e25177d4cf95d97965a5212c7fd.html