GetText
的方法是私有的:
private static string GetText(string path, string filename){var reader = File.OpenText($"{AppendPathSeparator(path)}{filename}");var text = reader.ReadToEnd();return text;string AppendPathSeparator(string filepath){return filepath.EndsWith(@"\") ? filepath : filepath + @"\";}}
本地函数的一个实用功能是可以允许立即显示异常 。
对于方法迭代器,仅在枚举返回的序列时才显示异常,而非在检索迭代器时 。
对于异步方法 , 在等待返回的任务时,将观察到异步方法中引发的任何异常 。
本地函数和lambda
表达式是十分相似的,但两者中选用一种的时机和条件其实是存在差别 。
// 本地函数public static int LocalFunctionFactorial(int n){return nthFactorial(n);int nthFactorial(int number) => number < 2? 1: number * nthFactorial(number - 1);}// Lambda 表达式public static int LambdaFactorial(int n){Func<int, int> nthFactorial = default(Func<int, int>);nthFactorial = number => number < 2? 1: number * nthFactorial(number - 1);return nthFactorial(n);}
本地函数的命名方式与方法相同 。Lambda
表达式是一种匿名方法,需要分配给 delegate
类型的变量,通常是 Action
或 Func
类型 。声明本地函数时,此过程类似于编写普通方法;声明一个返回类型和一个函数签名 。
Lambda
表达式在声明时转换为委托 。本地函数更加灵活,可以像传统方法一样编写,也可以作为委托编写 。只有在用作委托时,本地函数才转换为委托 。如果声明了本地函数 , 但只是通过像调用方法一样调用该函数来引用该函数,它将不会转换成委托 。
本地函数可以避免Lambda
表达式始终需要的堆分配 。如果本地函数永远不会转换为委托,并且本地函数捕获的变量都不会被其他转换为委托的Lambda
或本地函数捕获 , 则编译器可以避免堆分配 。
yield 关键字的用法:
// 可将本地函数作为迭代器实现,使用 yield return 语法生成一系列值public IEnumerable<string> SequenceToLowercase(IEnumerable<string> input){if (!input.Any())throw new ArgumentException("There are no items to convert to lowercase.");return LowercaseIterator();IEnumerable<string> LowercaseIterator(){foreach (var output in input.Select(item => item.ToLower()))yield return output;}}
虽然本地函数对 lambda 表达式可能有点冗余,但实际上它们的目的和用法都不一样 。如果想要编写仅从上下文或其他方法中调用的函数,则使用本地函数更高效 。
七、扩展 Expression bodied 成员在C# 6.0中已经新增了表达式主体定义,而在当前版本中进行了扩展 。扩展的内容包括下面几点 。
可以使用表达式主体定义来实现属性 get
和 set
访问器 。
public class Location{private string locationName;public Location(string name) => Name = name;public string Name{get => locationName;set => locationName = value;}}
构造函数的表达式主体定义通常包含单个赋值表达式或一个方法调用 , 该方法调用可处理构造函数的参数,也可初始化实例状态 。
// 其构造函数具有一个名为“name”的字符串参数,表达式主体定义向 Name 属性分配参数public class Location{private string locationName;public Location(string name) => Name = name;public string Name{get => locationName;set => locationName = value;}}
终结器的表达式主体定义通常包含清理语句,例如释放非托管资源的语句 。
// 定义一个终结器,该终结器使用表达式主体定义来指示已调用该终结器public class Destroyer{public override string ToString() => GetType().Name;~Destroyer() => Console.WriteLine($"The {ToString()} finalizer is executing.");}
索引器与使用属性一样,如果 get
访问器包含返回值的单个表达式或 set
访问器执行简单的赋值 , 则索引器 get
和 set
访问器包含表达式主体定义 。
using System;using System.Collections.Generic;// 其中包含一个内部 String 数组,该数组包含大量体育运动的名称// 索引器的 get 和 set 访问器都以表达式主体定义的形式实现public class Sports{private string[] types = { "Baseball", "Basketball", "Football","Hockey", "Soccer", "Tennis","Volleyball" };public string this[int i]{get => types[i];set => types[i] = value;}}
八、ref 局部变量在变量类型之前添加 ref
推荐阅读
- AgileBoot - 如何集成内置数据库H2和内置Redis
- 启初和小浣熊面霜哪个好_启初跟小浣熊哪个更好
- 3050和3050ti的差距_3050和3050ti差多少
- 华为nova9和华为nova9pro的区别_华为nova9和华为nova9pro有什么不同
- 荣耀magic3怎么设置指纹解锁_添加指纹解锁步骤
- TCP 序列号和确认号是如何变化的?
- 二 SpringCloud - Eureka注册中心,feign远程调用,hystrix降级和熔断
- 其三 Gitea 1.18 功能前瞻:增强文本预览效果、继续扩展软件包注册中心、增强工单实用功能、完善了用户邀请机制和SEO
- 华为watch3pro尊享版和时尚版区别_哪款更值得入买
- 雅萌ace和max的区别_雅萌ace和max的参数