• Framework 3.5学习笔记


        前一阶段vs2008终于正式推出了,忙着学习3.5的新功能,今天就写一下学习成果吧。(当然包括c# 3.0和vb9的新特性)
        个人感觉,新语法的最终要的两个语法是:扩展方法和Lambda表达式,当然不是说其它的新特性不重要,只是个人感觉比较简单,没有什么需要花大力气去学习的。

        扩展方法应该说是一个非常甜的语法糖,为了给一些类增加功能,必须要新建一个Utility,然后给出一些静态方法,调用时,还必须Utility.静态方法(实例,...)的绕圈方式调用,扩展方法从本质上还是这样子,只不过,在高级语言里面用非常简单的方式直接调用,编译器会自动找到适合的静态方法,并且在IL级别上还原为Utility.静态方法(实例,...)的形式。换而言之,在IL级别上根本没有什么扩展方法,IL上只有一个Utility类和几个静态方法而已。
        但是,这个不大的修改,确实在一方面极大的简化了编程者的时间和精力(要记住哪个特定Utility下有哪个特定静态方法也是一件很累得事情)。另一方面,也是表现出了IL在设计方面的超前性,运行时还是2.0的运行时,而且扩展方法本质上还是用的1.0起就存在的特性(Attribute),将特性和编译器相结合,就可以看到这个令人眩目的方案。

        在看看Lambda表达式,当时的第一感觉是2.0里面的匿名方法,确实,很多地方很像。
        对比c# 3.0与vb9,可以发现有几个方面不同:
        在c# 3.0中,必须要显式的告诉编译器,某个Lambda表达式是编译成一个匿名方法还是一个表达式树,如果不指明,编译器会报错,因此,不支持匿名委托。
        在vb9中,如果没有显式的告诉编译器要编译成一个表达式树,那么编译器就自动把Lambda表达式编译成一个匿名方法,因此可以理解为支持匿名委托。
        在c# 3.0中,因为匿名方法支持多行的表达式,因此,可以写一个多行语句的,或者没有返回值的Lambda表达式。
        在vb9中,Lambda表达式被限制在一句,并且必须要有返回值。

        因为这些不同,所以,有的时候感觉某些功能在c#中很简单,而另外一些功能在vb中很简单。
        举例来说,因为vb支持匿名委托,因此可以在声明完立即调用,而c#必须分开。vb在某些特例下更接近正统的函数式变成语言。但是c#却又能提供复杂的匿名方法,而vb却不得不显式的声明一个方法来完成对应的功能。
        来看一个特例,利用Y combinators来算阶乘:
        c#版的实现,摘自Mads
    public class Program
    {
      
    delegate T SelfApplicable<T>(SelfApplicable<T> self);

      
    static void Main(string[] args)
      
    {
         
    // The Y combinator
         SelfApplicable<Func<Func<Func<int,int>,Func<int,int>>,Func<int,int>>
         
    > Y = y => f => x => f(y(y)(f))(x);
         
    // The fixed point generator
         Func<Func<Func<intint>, Func<intint>>, Func<intint>> Fix = Y(Y);
         
    // The higher order function describing factorial
         Func<Func<int,int>,Func<int,int>> F = fac => x => x == 0 ? 1 : x * fac(x-1);
         
    // The factorial function itself
         Func<int,int> factorial = Fix(F);
         
    for (int i = 0; i < 12; i++)
         
    {
           Console.WriteLine(factorial(i));
         }

      }

    }
        在看一下vb的实现,载自装配中的脑袋
    Dim Y = Function(f As Func(Of Func(Of ObjectObject), Func(Of ObjectObject))) _
                        (
    Function(h As Func(Of Object, Func(Of ObjectObject))) Function(x) f(h(h))(x)) _
                        (
    Function(h As Func(Of Object, Func(Of ObjectObject))) Function(x) f(h(h))(x))

    Dim fact = Y(Function(self As Func(Of ObjectObject)) Function(n) If(n = 01, n * self(n - 1)))

    Dim result = fact(4)
        可以发现vb的写法非常简单,不过因为是用弱类型的缘故,计算时间是c#版的一倍。不过可以稍微改进一下:
    Shared Function Foo(Of T)(func As Func(Of Func(Of T, T), Func(Of T, T))) As Func(Of T, T) 
       
    Dim Y = Function(f As Func(Of Func(Of T, T), Func(Of T, T))) _ 
               (
    Function(h As Func(Of Object, Func(Of T, T))) Function(x) f(h(h))(x)) _ 
               (
    Function(h As Func(Of Object, Func(Of T, T))) Function(x) f(h(h))(x)) 
       
    Return Y(func) 
    End Function
     

    Sub Bar() 
       
    Dim fact = Foo(Of Integer)(Function(self) Function(n) If(n = 01, n * self(n - 1))) 
       
    Dim result = fact(4
    End Sub
        通过泛型把速度可以提升到接近c#版,并且,这个方法也可以被c#中直接引用,作为类库。当然,这里的速度和直接用代码递归实现的速度相差还是比较远,因为,其中要创建多个委托对象,而在计算阶乘的例子中,创建对象的代价相对于运算而言是相当昂贵的。

        当然,vb的缺点也说过了,不支持多句语句的Lambda表达式,可以说是个比较致命的伤,相对而言,c#在这方面就比较强。

        再说一下Lambda表达式和表达式树,以前在某个项目里面,我就写过一个简单的表达式树,当然不会像3.5的表达式树那样复杂,也不存在Compile方法,所有的计算是基于解析的,当然也有转换成Sql的实现(因为表达式比较少,所以实现相对比较简单)。但是,在与语言集成方面要大大一个折扣,用Linq可以轻松的创建一个表达式树,而不用在代码中不停的new节点。当然,如果要动态的添加修改表达式树,那么,就又回到了类似以前的方式。当然,在表达式的丰富程度上应该说是比较完善的,而且支持Compile方法,将表达式树变成IL。唯一比较遗憾的是,没有Compile的时候,不能通过参数解释运行表达式树获得结果(或者有这个方法,看漏了)。。。

        以上就是最近这一个月的学习笔记,下一个月继续学习Linq。
  • 相关阅读:
    指向老域名的反链丢失问题
    oracle express介绍
    VB6:通过ADO访问Oracle存储过程返回的结果集
    Oracle学习笔记:理解oracle的编程接口oo4o的对象模型
    Oracle学习笔记:oracle的编程接口
    VB6:编写一个分析sqlserver存储过程执行语句"execute procedurename par1,par2,......."语法是否正确的函数
    惊喜!使用Regcure修复注册表错误,Oracle客户端可以使用了
    最新30佳精美的名片设计作品欣赏
    28个经过重新设计的著名博客案例
    向设计师推荐20款漂亮的免费英文字体
  • 原文地址:https://www.cnblogs.com/vwxyzh/p/1023169.html
Copyright © 2020-2023  润新知