C# 7.0 新特性:本地方法
C# 7.0:本地方法
VS 2017 的 C# 7.0 中引入了本地方法,本地方法是一种语法糖,允许我们在方法内定义本地方法。更加类似于函数式语言,但是,本质上还是基于面向对象实现的。
1. 本地方法
先看一个示例:
using static System.Console; namespace UseLocalFunctions
{
class Program
{
static void Main(string[] args)
{
void Add(int x, int y)
{
WriteLine($"Sum of {x} and {y}: is {x + y}");
} void Multiply(int x, int y)
{
WriteLine($"Multiply of {x} and {y} is: {x * y}");
Add(, );
} Add(, );
Multiply(, ); ReadLine();
}
}
}
在此示例中,在 Main 方法内,嵌套定义了两个方法:Add 和 Multiply。这个方法可以在 Main 方法内被使用。这种方法被称为本地方法。英文称为:Local function.
使用 ILDasm 工具,可以看到编译之后的结果。

这两个本地方法被翻译成了两个静态的私有方法,它只能在定义的方法内被调用。
本地方法的语法定义为:
<modifiers: async | unsafe> <return-type> <method-name> <parameter-list>
方法的修饰符只有两种:async 和 unsafe,所有的本地方法都是私有的
- 如果您使用了 private 修饰,会收到 编译器的错误提示:error CS0106, "The modifier 'static' is not valid for this item."
- 如果您使用了 static,会收到编译器的错误提示:error CS0106, "The modifier 'static' is not valid for this item."
2. 带有返回类型的本地方法
本地方法也可以带有返回类型。如果类型用错的话,Visual Studio 可以给出提示。
class Program
{
static void Main(string[] args)
{
PrintStudentMarks(,
new Subject
{
SubjectName = "Math",
Marks =
}, new Subject
{
SubjectName = "physics",
Marks =
}, new Subject
{
SubjectName = "Chem",
Marks =
}); ReadLine();
} public static void PrintStudentMarks(int studentId, params Subject[] subjects)
{
WriteLine($"Student Id{studentId} Total Marks: {CalculateMarks()}");
WriteLine($"Student wise marks");
foreach(var subject in subjects)
{
WriteLine($"Subject Name: {subject.SubjectName}\t Marks: {subject.Marks}");
} decimal CalculateMarks()
{
decimal totalMarks = ;
foreach(var subject in subjects)
{
totalMarks += subject.Marks;
} return totalMarks;
}
} public class Subject
{
public string SubjectName
{
get; set;
} public decimal Marks
{
get; set;
}
}
}
3. 使用本地方法实现递归
本地方法不需要维护调用堆栈,而递归方法需要维护调用堆栈,本地方法效率更高。下面的示例演示了两种方法的区别。
注意:该示例使用了类型 BigInteger ,需要添加对程序集 System.Numeric.dll 的引用。

代码如下。
class Program
{
static void Main(string[] args)
{
Stopwatch watch = new Stopwatch();
watch.Start();
BigInteger f1 = GetFactorialUsingLocal();
watch.Stop();
WriteLine($"Using local function: {watch.ElapsedTicks}"); watch.Reset();
watch.Start();
BigInteger f2 = GetFactorial();
watch.Stop();
WriteLine($"Using recursive function: {watch.ElapsedTicks}");
} private static BigInteger GetFactorialUsingLocal(int number)
{
if (number < )
throw new ArgumentException("negative number", nameof(number));
else if (number == )
return ;
BigInteger result = number;
while (number > )
{
Multiply(number - );
number--;
} void Multiply(int x) => result *= x;
return result;
} private static BigInteger GetFactorial(int number)
{
if (number < )
throw new ArgumentException("nagative number", nameof(number));
return number == ? : number * GetFactorial(number - );
}
}
在我的机器上,结果如下:
Using local function: 181770
Using recursive function: 456602
可以看到两者之间的性能差异。
此时,为了传递 result ,在生成的代码中,编译器会自动做一些额外的工作。

4. 本地方法与 Lambda 的比较
1. 性能
当创建 Lambda 的时候,将会创建一个委托,这需要内存分配,因为委托是一个对象。而本地方法则不需要,它是一个真正的方法。
另外,本地方法可以更为有效地使用本地变量,Lambda 将变量放到类中,而本地方法可以使用结构,而不使用内存分配。
这意味着调用本地方法更为节约且可能内联。
2. 本地方法可以递归
Lambda 也可以实现递归,但是代码丑陋,您需要先赋予 lambda 为 null。本地方法可以更为自然地递归。
3. 本地方法可以使用泛型
Lambda 不能使用泛型。这是因为需要赋予一个实例类型的变量。
4. 本地方法可以实现迭代器
Lambda 不能使用 yield return (以及 yield break)关键字,以实现 IEnumerable<T> 返回函数。本地方法可以。
5. 本地方法更为易读
5. 其它资源:
C# 7.0 新特性:本地方法的更多相关文章
- C# 7.0 新特性2: 本地方法
本文参考Roslyn项目中的Issue:#259. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: 模式匹配 ...
- C# 7.0 新特性1: 基于Tuple的“多”返回值方法
本文基于Roslyn项目中的Issue:#347 展开讨论. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: ...
- C# 7.0 新特性3: 模式匹配
本文参考Roslyn项目Issue:#206,及Docs:#patterns. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# ...
- C# 7.0 新特性4: 返回引用
本文参考Roslyn项目中的Issue:#118. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: 模式匹配 ...
- c# 6.0新特性(二)
写在前面 上篇文章介绍了c#6.0的using static,Auto Property Initializers,Index Initializers新的特性,这篇文章将把剩下的几个学习一下. 原文 ...
- C#6.0,C#7.0新特性
C#6.0新特性 Auto-Property enhancements(自动属性增强) Read-only auto-properties (真正的只读属性) Auto-Property Initia ...
- 【c#】6.0与7.0新特性介绍记录
c#发展史 引用地址:https://www.cnblogs.com/ShaYeBlog/p/3661424.html 6.0新特性 1.字符串拼接优化 语法格式:$”string {参数}” 解释: ...
- Javaweb学习笔记——(七)——————myexlipse基本使用、jdk5.0新特性及反射讲解
1.debug调试模式: *使用这种模式,调试程序(看到程序运行停止在这一行) -显示出来行号 -双击左边,出现一个圆点,表示设置了一个断点 *使用debug as方式,运行程序 -特使是否进入到调试 ...
- webpack 4.0.0-beta.0 新特性介绍
webpack 可以看做是模块打包机.它做的事情是:分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式 ...
随机推荐
- Laravel学习基础篇之--路由
终于还是决定再多学一门重量级框架,当然首选必备还是被称为最优雅的Web开发框架--Laravel 对于框架的入门,首先了解它的路由规则是先前必备的,以下是laravel 中几种常见的基础路由规则 // ...
- 浅析SQL Server在可序列化隔离级别下,防止幻读的范围锁的锁定问题
本文出处:http://www.cnblogs.com/wy123/p/7501261.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...
- C# 实现AOP 的几种常见方式
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的中统一处理业务逻辑的一种技术,比较常见的场景是:日志记录,错误捕获 ...
- Http get方式url参数长度以及大小
详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp69 众所周知, 传递小量参数(在没有其他原因,例如隐藏参数值的情况下)推 ...
- 《Java程序设计》终极不改版
半年前的作品,上传只为纪念~ 成绩: ____0.1______ Java程序设计 课程设计 题 目:大学生信息管理系统 学 院: 计算机与软件学院 专 业: 网络工程_____ . ...
- 第六次meeting会议
[Beta] 第六次Daily Scrum Meeting 一.本次会议为第六次meeting会议 二.时间:10:00AM-10:20AM 地点:禹州楼 三.会议站立式照片 四.今日任务安排 成员 ...
- GUI记事本+切换面板1.1版
package com.niit.javagui; import java.awt.Color; import java.awt.MenuBar; import java.awt.event.Inpu ...
- 作业2——英语学习APP的案例分析
英语学习APP的案例分析 很多同学有误解,软件工程课是否就是理论课?或者是几个牛人拼命写代码,其他人打酱油的课?要不然就是学习一个程序语言,搞一个职业培训的课?都不对,软件工程有理论,有实践,更重要的 ...
- 团队作业4——第一次项目冲刺(Alpha版本)2017.4.22
昨天来不及编写,这是4月22日的日志,现在补上. 1.开完站立式会议后的合照 2.任务分解图 3.开会讨论的结果,任务分派 队员 今日进展 明日安排 陈鑫龙 原型设计图分析,设计登陆界面原稿 实现登陆 ...
- 201521123050 《Java程序设计》第7周学习总结
1. 本周学习总结 2. 书面作业 1.ArrayList代码分析 1.1 解释ArrayList的contains源代码 代码: public boolean contains(Object o) ...