VB中的Closure:第1部分

[原文作者]Jared Parsons

[原文链接]Closures in VB: Part 1

我叫Jared Parsons,是微软VB编译和调试组的软件开发人员。我为VB9.0开发的一个新特性叫做“lexical closure支持。这个特性是对VB语言的一个重要扩充,因此我将通过几篇博客来解释这一特性是如何影响你的代码。

LexicalClosures(通常被简称为Closures)是Visual Basic 9.0几个新特性的内在支持,是Lambda和查询表达式的内在实质。我将针对VB9.0的Closures工作机制,局限性以及使用时易犯的错误将做系列性介绍。

首先,我们从一个基本的结论:什么是closure开始说起吧。在Wikipedia的定义是“...用于关联方法与环境的语法概念...”,但我更喜欢这样来描述它:一个Closure是一个特性,该特性允许用户从多个函数访问某一个环境(局部变量,参数和方法)。举例说明可能更易说明清楚:)

    Class C1
        Sub Test()
            Dim x = 5
            Dim f = Function(ByVal y As Integer) x + y
            Dim result = f(42)
        End Sub 
    End Class

在这段代码中,包含了一个Lambda表达式。它有一个方法参数并将这个参数与“Test”的局部变量做累加。在VB中,Lambda表达式被作为函数来实现的(C#也一样)。所以,现在我们有2个方法,它们是“Test”“f”方法。“f“方法将访问“Test”方法的局部变量xclosure将在这里发挥其功效了。Closures负责使变量x在同一个进程中对于2个方法都可用(这被称为提升变量)。

要做到这点,编译器将执行4个步骤的操作:

1.        创建一个类,用于包含x以便在2个方法之间共享这个变量。这里,这个类称为Closure

2.        编译器将在这个Closure类中为Lambda表达式创建一个新方法。这里,这个方法名叫f

3.        编译器将在Test方法内部创建一个该Closure类的实例

4.        在“Test“方法中,将所有对于x的访问都重新改写为访问Closure类的成员变量x.

    Class Closure
        Public x As Integer 
        Function f(ByVal y As Integer) As Integer
            Return x + y
        End Function
    End Class 
    Class C1
        Sub Test()
            Dim c As New Closure()
            c.x = 5
            Dim f As Func(Of Integer, Integer) = AddressOf c.f
            Dim result = f(42)
        End Sub 
    End Class

现在,两个方法都可以共享变量x了。同时,用户也无需了解任何有关编译器实际产生的代码。你可以从这个简单例子中了解到closure和所有其它VB9.0新特性(类型推断,Lambda表达式)是如何为你节省代码量的了。

注意:这个例子只是模拟了当使用Closure时编译器所产生的代码,但是实际生成的代码却看起来不是这么“优雅”,反而还用了许多难以理解的名字,如“$Lambda_1”等。

下次,我将深入地阐述一些closure更多的使用(多变量,方法访问,术语等)。

Jared Parsons

LINQ 菜谱, 菜单1: 改变Windows 窗体上所有标签的字体

[原文作者]: Kit George

[原文链接]: LINQ Cookbook, Recipe 1: Change the font for all labels on a windows form

 

我们打算启动一个LINQ菜谱项目,并逐步将它完成。这个项目的目的是为你在编程和用查询时遇到的一些特殊情况提供解决的方案。我再也想不出一个更好的方式,来关联你能利用LINQ所做的每件事情了。

 

这个系列项目主要是为您展示LINQ可以做到的各式各样的事情。像任何一本好菜谱一样,我们将为这本菜谱做分类,那样你之后就可以很容易地查询。但是不要希望一个特定的菜谱会有大量的描述,尽管它会包含重现步骤。请尽管向我们要求任何你想要看到的菜谱,而我们将尽可能多地创造新的。

 

材料:

      Visual Studio 2008 (Beta2 或更高版本)

 

类别:

      LINQ-To-ObjectsLINQ with Windows FormsLINQ with controlsLabel

 

制作方法:

      打开 Visual Studio 2008,点击文件/新建项目找到并双击Windows窗体应用程序图标。

      增加窗体的大小,使其足够容纳一定数量的控件。

      从工具箱中拖放几个控件到窗体上,确保至少添加3-4个标签控件。

      o  我个人比较喜欢的是两个分组控件(GroupBox)在文本框(TextBox)前放两个标签(Label)(标签在分组控件之上)并在每个分组控件中放一对单选框(RadioButton)控件。这样可以确保测试递归代码。

      添加一个按钮到窗体上并把它的Text属性改为Go双击这个按钮,然后修改事件处理代码并添加下面的方法:

 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        For Each label In GetLabels(Me)

            label.Font = New Font(“Comic Sans MS”, 12, _

                                  FontStyle.Bold Or FontStyle.Underline)

        Next

    End Sub

 

    Private Function GetLabels(ByVal sourceControl As Control) _

                               As IEnumerable(Of Control)

        If sourceControl.Controls.Count > 0 Then

            Dim labels = From cont As Control In sourceControl.Controls _

                         Where TypeOf cont Is Label _

                         Select cont

 

            For Each c As Control In sourceControl.Controls

                labels = labels.Union(GetLabels(c))

            Next

 

            Return labels

        End If

 

        Return New List(Of Control)

    End Function

 

     修改New Font所在的那行代码为你想要的字体样式。