svi*_*ick 256
Mads Torgersen在C#设计会议笔记中对此进行了解释,其中首先讨论了本地函数:
你想要一个辅助功能.您只在单个函数中使用它,它可能使用包含函数的范围内的变量和类型参数.另一方面,与lambda不同,您不需要它作为第一类对象,因此您不必为它赋予委托类型并分配实际的委托对象.您也可能希望它是递归的或泛型的,或者将其实现为迭代器.
为了进一步扩展它,优点是:
性能.
创建lambda时,必须创建一个委托,在这种情况下这是一个不必要的分配.本地函数实际上只是函数,不需要代理.
此外,本地函数在捕获局部变量时更有效:lambdas通常将变量捕获到类中,而本地函数可以使用struct(传递使用ref
),这又避免了分配.
这也意味着调用本地函数更便宜并且可以内联,可能进一步提高性能.
本地函数可以递归.
Lambdas也可以递归,但它需要笨拙的代码,首先分配null
给委托变量然后分配lambda.本地函数自然可以递归(包括相互递归).
本地功能可以是通用的.
Lambdas不能是通用的,因为它们必须被赋值给具有具体类型的变量(该类型可以使用来自外部作用域的泛型变量,但这不是同一个东西).
本地函数可以实现为迭代器.
Lambdas不能使用yield return
(和yield break
)关键字来实现 - IEnumerable<T>
返回功能.本地功能可以.
本地功能看起来更好.
这在上面的引用中没有提到,可能只是我个人的偏见,但我认为正常的函数语法看起来比将lambda赋给委托变量要好.本地功能也更简洁.
相比:
int add(int x, int y) => x + y;
Func<int, int, int> add = (x, y) => x + y;
Run Code Online (Sandbox Code Playgroud)Tim*_*ann 76
除了svick的好答案之外,本地函数还有一个优点:
它们可以在函数的任何地方定义,甚至在return
语句之后.
public double DoMath(double a, double b)
{
var resultA = f(a);
var resultB = f(b);
return resultA + resultB;
double f(double x) => 5 * x + 3;
}
Run Code Online (Sandbox Code Playgroud)
如果您还想知道如何测试本地功能,则应检查JustMock,因为它具有执行此功能的功能。这是一个将被测试的简单类示例:
public class Foo // the class under test
{
public int GetResult()
{
return 100 + GetLocal();
int GetLocal ()
{
return 42;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是测试的外观:
[TestClass]
public class MockLocalFunctions
{
[TestMethod]
public void BasicUsage()
{
//Arrange
var foo = Mock.Create<Foo>(Behavior.CallOriginal);
Mock.Local.Function.Arrange<int>(foo, "GetResult", "GetLocal").DoNothing();
//Act
var result = foo. GetResult();
//Assert
Assert.AreEqual(100, result);
}
}
Run Code Online (Sandbox Code Playgroud)
这是JustMock 文档的链接。
我很好奇本地函数到底比 lambda 快多少,所以我写了一些基准测试:
[Benchmark]
public void TestLambda()
{
Func<int, int> _Square = (x) => x * x;
_Square(123);
}
[Benchmark]
public void TestLocalFunc()
{
int _Square(int x) => x * x;
_Square(123);
}
Run Code Online (Sandbox Code Playgroud)
结果令我震惊。
| Method | Mean | Error | StdDev | Median | Allocated |
|-------------- |----------:|----------:|----------:|----------:|----------:|
| TestLambda | 1.4949 ns | 0.1997 ns | 0.0109 ns | 1.4898 ns | - |
| TestLocalFunc | 0.0008 ns | 0.0237 ns | 0.0013 ns | 0.0000 ns | - |
// * Warnings *
ZeroMeasurement
BenchMark.TestLocalFunc: ShortRun -> The method duration is indistinguishable from the empty method duration
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
17317 次 |
最近记录: |