当前位置: 首页 > ds >正文

windows C#-本地函数

本地函数是一种嵌套在另一成员中的类型的方法。 仅能从其包含成员中调用它们。 可以在以下位置中声明和调用本地函数:

  • 方法,尤其是迭代器方法和异步方法
  • 构造函数
  • 属性访问器
  • 事件访问器
  • 匿名方法
  • Lambda 表达式
  • 终结器
  • 其他本地函数

但是,不能在 expression-bodied 成员中声明本地函数。

在某些情况下,可以使用 lambda 表达式实现本地函数也支持的功能。 

本地函数可使代码意图明确。 任何读取代码的人都可以看到,此方法不可调用,包含方法除外。 对于团队项目,它们也使得其他开发人员无法直接从类或结构中的其他位置错误调用此方法。

本地函数语法

本地函数被定义为包含成员中的嵌套方法。 其定义具有以下语法:

<modifiers> <return-type> <method-name> <parameter-list>

<parameter-list> 不应包含使用上下文关键字 value 命名的参数。 编译器创建临时变量“value”,其中包含引用的外部变量,这在以后会导致歧义,还可能导致意外行为。

可以将以下修饰符用于本地函数:

  • async
  • unsafe
  • static 静态本地函数无法捕获局部变量或实例状态。
  • extern 外部本地函数必须为 static。

在包含成员中定义的所有本地变量(包括其方法参数)都可在非静态本地函数中访问。

与方法定义不同,本地函数定义不能包含成员访问修饰符。 因为所有本地函数都是私有的,包括访问修饰符(如 private 关键字)会生成编译器错误 CS0106“修饰符‘private’对于此项无效”。

以下示例定义了一个名为 AppendPathSeparator 的本地函数,该函数对于名为 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 + @"\";}
}

可将属性应用于本地函数、其参数和类型参数,如以下示例所示:

#nullable enable
private static void Process(string?[] lines, string mark)
{foreach (var line in lines){if (IsValid(line)){// Processing logic...}}bool IsValid([NotNullWhen(true)] string? line){return !string.IsNullOrEmpty(line) && line.Length >= mark.Length;}
}

前面的示例使用特殊属性来帮助编译器在可为空的上下文中进行静态分析。

本地函数和异常

本地函数的一个实用功能是可以允许立即显示异常。 对于迭代器方法,仅在枚举返回的序列时才显示异常,而非在检索迭代器时。 对于异步方法,在等待返回的任务时,将观察到异步方法中引发的任何异常。

以下示例定义 OddSequence 方法,用于枚举指定范围中的奇数。 因为它会将一个大于 100 的数字传递到 OddSequence 迭代器方法,该方法将引发 ArgumentOutOfRangeException。 如示例中的输出所示,仅当循环访问数字时才显示异常,而非检索迭代器时。

public class IteratorWithoutLocalExample
{public static void Main(){IEnumerable<int> xs = OddSequence(50, 110);Console.WriteLine("Retrieved enumerator...");foreach (var x in xs)  // line 11{Console.Write($"{x} ");}}public static IEnumerable<int> OddSequence(int start, int end){if (start < 0 || start > 99)throw new ArgumentOutOfRangeException(nameof(start), "start must be between 0 and 99.");if (end > 100)throw new ArgumentOutOfRangeException(nameof(end), "end must be less than or equal to 100.");if (start >= end)throw new ArgumentException("start must be less than end.");for (int i = start; i <= end; i++){if (i % 2 == 1)yield return i;}}
}
// The example displays the output like this:
//
//    Retrieved enumerator...
//    Unhandled exception. System.ArgumentOutOfRangeException: end must be less than or equal to 100. (Parameter 'end')
//    at IteratorWithoutLocalExample.OddSequence(Int32 start, Int32 end)+MoveNext() in IteratorWithoutLocal.cs:line 22
//    at IteratorWithoutLocalExample.Main() in IteratorWithoutLocal.cs:line 11

如果将迭代器逻辑放入本地函数,则在检索枚举器时会引发参数验证异常,如下面的示例所示:

public class IteratorWithLocalExample
{public static void Main(){IEnumerable<int> xs = OddSequence(50, 110);  // line 8Console.WriteLine("Retrieved enumerator...");foreach (var x in xs){Console.Write($"{x} ");}}public static IEnumerable<int> OddSequence(int start, int end){if (start < 0 || start > 99)throw new ArgumentOutOfRangeException(nameof(start), "start must be between 0 and 99.");if (end > 100)throw new ArgumentOutOfRangeException(nameof(end), "end must be less than or equal to 100.");if (start >= end)throw new ArgumentException("start must be less than end.");return GetOddSequenceEnumerator();IEnumerable<int> GetOddSequenceEnumerator(){for (int i = start; i <= end; i++){if (i % 2 == 1)yield return i;}}}
}
// The example displays the output like this:
//
//    Unhandled exception. System.ArgumentOutOfRangeException: end must be less than or equal to 100. (Parameter 'end')
//    at IteratorWithLocalExample.OddSequence(Int32 start, Int32 end) in IteratorWithLocal.cs:line 22
//    at IteratorWithLocalExample.Main() in IteratorWithLocal.cs:line 8
http://www.xdnf.cn/news/15983.html

相关文章:

  • 【计算机组成原理】原码、补码和移码
  • ZooKeeper学习专栏(一):分布式协调的核心基石
  • 阶段1--Linux中的计划任务
  • 大模型词表设计与作用解析
  • 开源安全大模型Foundation-Sec 8B的安全实践
  • Baumer工业相机堡盟工业相机如何通过YoloV8的深度学习模型实现螺母螺丝的分类检测(C#代码,UI界面版)
  • 【开源项目】基于RuoYi-Vue-Plus的开源进销存管理系统
  • 软件工程:需求分析
  • XSS内容总结
  • 建筑墙壁损伤缺陷分割数据集labelme格式7820张20类别
  • 从零到精通:用DataBinding解锁MVVM的开发魔法
  • 优先算法——专题十:哈希表
  • JAVA高级第六章 输入和输出处理(一)
  • 人工智能与心理史学:从阿西莫夫的科幻预言到可计算社会模型>
  • 车载通信架构 --- DoIP协议通信
  • Java多线程基础详解:从实现到线程安全
  • CS231n-2017 Lecture2图像分类笔记
  • Map集合
  • C++入门--lesson4
  • 嵌入式学习-PyTorch(9)-day25
  • HTTPHTTPSTLSDNSRSA
  • Python技术题2
  • 工程图矢量化 笔记 | potrace ezdxf svgpathtools | png转svg保存dxf用matplotlib画出来
  • 如何构建未来的人-AI-环境智能教育生态系统
  • 线性回归问题
  • xss的利用
  • 《YOLOv13魔术师专栏》全景指南:从理论到工业级实战
  • ICT测试原理之--什么是假短
  • JavaSE-接口
  • Android14 SystemUI 启动流程(2)