本文参考Roslyn项目中的Issue:#259.

  1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法

  2. C# 7.0 新特性2: 本地方法

  3. C# 7.0 新特性3: 模式匹配

  4. C# 7.0 新特性4: 返回引用

简而言之,【本地方法】就是在方法体内部定义一个方法

其实咋眼一看,这个新特新并没有什么新意,因为目前大量C#的项目中,都可以使用delegate或基于delegate变形的各种方案(lambda, Fun<*>, Action, Action<*> ...)。

但是请仔细推敲一下,方法体内部delegate,是否真的那么完美无缺……

目前的C#

我们看一下,通常方法内部设置子逻辑单元的做法。

 public void Bar()
{
var arr= new int[] { , ,, };
Func<int, string> handler = i => $"当前值是:{i}。";
foreach (var i in arr)
{
Console.WriteLine(handler(i));
}
}

看起来有什么问题吗?当然,很多。

  1. 首先,handler是无法进行递归调用的,看下面的代码。

 public int Bar(int n)
{
if (n < ) throw new ArgumentException();
Func<int, int> handler = n => {
if (n == ) return ;
return n * handler(n - 1);
};
return handler(n);
}

  这时handler(n-1) 的调用会报错(Use of unassigned local variable 'handler'),原因是handler还未被赋值。通常,这种问题我们会尝试用一种非常难看的做法变通解决:

 Func<int, int> handler = null;
handler = n =>{
if (n == ) return ;
return n * handler(n - );
};

  咳咳咳,不多说了,心里一万只羊驼狂奔而过。

  2. 其次,Lambda表达式的使用,非常有局限,它不允许在参数中添加行为修饰 out, ref, params, 以及可选参数,均不能在Lambda表达式的参数表中出现。参数无法使用泛型。

  3. 分配了一个委托对象来指向函数,为了能够在Lambda表达式中访问本地变量,会为其分配一个新的对象,间接的增加了GC的压力。

说到这里,可能有的童鞋会自然的想到更原始的解决方案,在外部声明一个私有函数,就不会存在以上一系列的问题。

 class Foo
{
public void Bar(int[] arr)
{
foreach(var i in arr)
{
Console.WriteLine(Handler(i));
}
} private string Handler(int i) => $"当前值是:{i}";
}

这的确是一种简单粗暴的解决方案,但是依然存在一些小问题,一个仅在Bar方法中有引用的方法,逻辑上也没必要暴露给this的其他成员。这种做法其实是结构上的一种不合理。

本地方法(Local Function)

在C#7.0中,允许代码直接在一个方法体(方法,构造,属性的Getter和Setter)里声明并调用子方法。

废话不说,上代码:

 public void Bar(int[] arr)
{
var length = arr.Length;
string Length() {
return $"length is {length}";
}
//或:
//string Length() => $"length is {length}";
Length();
}

上面例子中的Length(),在编译后会转化成当前类的私有成员方法(IL: this.<Bar>g__Length(): string()),但由于在C#语言层面做出了限制,只被允许在Bar方法中访问。

由于对this而言,是以类似匿名方法的形态存在,所以,在当前类中仍然可以定义同名且同样声明的成员方法,从所在的方法体中调用,会执行本地方法。

Okay,话说回来,由于它的本质成员方法,所以它可以避免 [委托 / Lambda表达式] 的种种限制,可以异步,可用泛型,可用out, ref, param, 可以yield, 特性参数, 等等。。

来个例子:

 class Foo
{
public IEnumerable<T> Bar<T>(params T[] items)
{
if (items == null) throw new ArgumentException(nameof(items)); IEnumerable<T2> Enumerate<T2> ([CallerMemberName] T2[] array) //使用泛型及特性参数
{
//本地方法逻辑
foreach (var item in array)
{
yield return item; //使用迭代器
}
} return Enumerate<T>(items); //调用本地方法
//return this.Enumerate<T>(items); //调用成员方法
} IEnumerable<T2> Enumerate<T2>([CallerMemberName] T2[] array)
{
//成员方法逻辑
}
}

总结

这个feature可以看出,C#在朝着函数式语言谨慎的调整。回想起很多人在首次接触代码的懵懂期,经常犯一种比较低级的错误,傻傻的尝试在Main方法中写函数声明,现在看来,那才是最直接的思维逻辑。

本文链接:http://www.cnblogs.com/ylvict/p/5579350.html  (转载请注明)

目前(2016年6月)C#7.0还未正式发布,大家如果想体验部分特性,可以去下载VS15预览版,最终发布的语法可能和本文中提及的有所不同,最新动态请大家关注Roslyn项目。

C# 7.0 新特性2: 本地方法的更多相关文章

  1. C# 7.0 新特性:本地方法

    C# 7.0:本地方法 VS 2017 的 C# 7.0 中引入了本地方法,本地方法是一种语法糖,允许我们在方法内定义本地方法.更加类似于函数式语言,但是,本质上还是基于面向对象实现的. 1. 本地方 ...

  2. C#3.0新特性之扩展方法介绍

    C#3.0扩展方法是给现有类型添加一个方法.现在类型即可是基本数据类型(如int,String等),也可以是自己定义的类.以下是引用片段: //Demo--1 //扩展基本类型 namespace T ...

  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: ...

  4. C# 7.0 新特性3: 模式匹配

    本文参考Roslyn项目Issue:#206,及Docs:#patterns. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# ...

  5. C# 7.0 新特性4: 返回引用

    本文参考Roslyn项目中的Issue:#118. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: 模式匹配 ...

  6. c# 6.0新特性(二)

    写在前面 上篇文章介绍了c#6.0的using static,Auto Property Initializers,Index Initializers新的特性,这篇文章将把剩下的几个学习一下. 原文 ...

  7. C#6.0,C#7.0新特性

    C#6.0新特性 Auto-Property enhancements(自动属性增强) Read-only auto-properties (真正的只读属性) Auto-Property Initia ...

  8. 【c#】6.0与7.0新特性介绍记录

    c#发展史 引用地址:https://www.cnblogs.com/ShaYeBlog/p/3661424.html 6.0新特性 1.字符串拼接优化 语法格式:$”string {参数}” 解释: ...

  9. Javaweb学习笔记——(七)——————myexlipse基本使用、jdk5.0新特性及反射讲解

    1.debug调试模式: *使用这种模式,调试程序(看到程序运行停止在这一行) -显示出来行号 -双击左边,出现一个圆点,表示设置了一个断点 *使用debug as方式,运行程序 -特使是否进入到调试 ...

随机推荐

  1. 解决easy ui 1.4datebox控件不能清空的问题

    用easy ui遇到这个问题,在网上找到了解决方案,不过是1.3.6版本的.现提供1.4版本的修改的具体位置和代码. 我们用的是这个 修改位置:12739行,添加代码: , { text: funct ...

  2. Mysql查询阻塞初探

    第一次值班,报警打电话给我说,数据库复制延时一个多小时,那个时候是半夜啊,但我还是很清醒的起来,开机.vpn.登录.show processlist,结果发现情况是这样的: 红线框表示的是当前每个线程 ...

  3. Softmax回归(Softmax Regression)

    转载请注明出处:http://www.cnblogs.com/BYRans/ 多分类问题 在一个多分类问题中,因变量y有k个取值,即.例如在邮件分类问题中,我们要把邮件分为垃圾邮件.个人邮件.工作邮件 ...

  4. 设计模式C#实现(十二)——装饰模式

    意图 0 适用性 1 结构 2 实现 3 效果 4 参考 5 意图 动态的给一个对象添加一些额外的职责. 适用性 动态的为单个对象添加职责而不影响其他对象 处理那些可以撤销的职责(? 在某些功能不需要 ...

  5. 照片大管家iOS-实现本地相册、视频、安全保护、社交分享一站式功能,源码开放

    <照片大管家> APP功能: 1.本地照片批量导入与编辑 2.本地视频存储与播放 3.手势密码.数字密码.TouchID安全保护 4.QQ.微信.微博.空间社交分享 5.其他细节功能. 运 ...

  6. android JAVA字符串转日期或日期转字符串(转)

    用法: SimpleDateFormat sdf = new SimpleDateFormat( " yyyy-MM-dd HH:mm:ss " ); 这一行最重要,它确立了转换的 ...

  7. Linux vim编辑命令

    yum install -y vim-enhanced 安装vim 命令 一般模式 shift 4 行尾 shift 6 或 0行首 gg 顶部 G 下部 复制 yy 剪切几行  数字 dd p粘贴 ...

  8. Qt model和tableview的使用

    QT中的model和tableview都是采用index索引   index含有两个成员变量一个是row   一个是column  对应该索引的行号.列号 model提供数据    view提供视图  ...

  9. HashMap的key可以是可变的对象吗???

    大家都知道,HashMap的是key-value(键值对)组成的,这个key既可以是基本数据类型对象,如Integer,Float,同时也可以是自己编写的对象,那么问题来了,这个作为key的对象是否能 ...

  10. Linux nm命令

    一.简介 显示关于对象文件.可执行文件以及对象文件库里的符号信息. 二.选项 http://www.cnblogs.com/wangkangluo1/archive/2012/07/02/257243 ...