当使用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()
对我来说是新的。我的问题是,这种方法已经使用了多长时间了,过去可能存在的可读性问题还有使用它的不利之处吗?
请注意,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;
}
}