寻找lambda调用速记文档

问题描述 投票:1回答:1

当使用var块声明返回该变量初始值的数据上下文时,我无法隐式地Dim / Using一个变量时,我总是会遇到问题。例如,

Dim classifications As IEnumerable(Of RT_Classification)
Using dc As New MyDataContext
    classifications = dc.RT_Classifications.OrderBy(Function(c) c.Order).ToList()
End Using

声明变量时,必须显式提供RT_Classification类型。与Using比较,不仅限于查询

Dim classifications = dc.RT_Classifications.OrderBy(Function(c) c.Order).ToList()

其中包含隐式内容,类似于c#中的var。但是,数据上下文必须包含声明,并包含变量classifications的整个上下文,这是不希望的。

我认为使用lambda基本上可以解决问题

Dim classifications =
    (Function()
        Using dc As New MyDataContext
            Return dc.RT_Classifications.OrderBy(Function(c) c.Order).ToList()
        End Using
    End Function).Invoke()

但是似乎有点笨重。但是,在了解了()的简写.Invoke()和IDE建议删除( )的情况下,我想到了一个看起来很奇怪但有效的代码

Dim classifications =
    Function()
        Using dc As New MyDataContext
            Return dc.RT_Classifications.OrderBy(Function(c) c.Order).ToList()
        End Using
    End Function()

请注意尾随的End Function()对我来说是新的。我的问题是,这种方法已经使用了多长时间了,过去可能存在的可读性问题还有使用它的不利之处吗?

vb.net lambda syntax
1个回答
0
投票

请注意,End Function()不是一种特殊的语法。它完全等效于您对f()的调用,或者将整个表达式都用括号括起来。

在解析()速记之前,编译器将编译整个lambda表达式,将其移动到单独的方法,并在您的代码中将其替换为指向该方法的委托。因此,当编译器继续解析您的代码时,它看到的只是以下内容:ThisIsADelegate()

如果您使用ILSpy之类的工具反编译应用程序,这将变得很明显。

原始代码:

Public Class TheseAreLambdas
    Dim values As String() = {"This", "word", "is", "the", "longest"}

    Dim classifications =
        Function()
            Return values.OrderBy(Function(s) s.Length).ToList()
        End Function()

    Public Sub DoSomething()
        'I used DirectCast just to reduce mess in the decompiled code. Not necessary otherwise.
        MessageBox.Show(DirectCast(classifications, List(Of String)).Count.ToString())
    End Sub
End Class

反编译代码:

public class TheseAreLambdas
{
    private string[] values;
    private object classifications;

    public TheseAreLambdas()
    {
        /*
            All variable initializations are automatically moved to the constructor.
        */

        //Our array of values.
        values = new string[5]
        {
            "This",
            "word",
            "is",
            "the",
            "longest"
        };

        //Our lambda expression, moved to a method called "_Lambda$__1", wrapped in
        //a compiler-generated delegate and invoked on the spot (notice the parenthesis on the end).
        classifications = new VB$AnonymousDelegate_1<List<string>>(_Lambda$__1)();
    }

    public void DoSomething()
    {
        MessageBox.Show(((List<string>)classifications).Count.ToString());
    }

    [CompilerGenerated]
    private List<string> _Lambda$__1() //Our lambda expression used for the "classifications" variable.
    {
        return values.OrderBy((string s) => s.Length).ToList();
    }

    [CompilerGenerated]
    private static int _Lambda$__2(string s)
    {
        return s.Length;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.