C# 语法中级

server/2025/1/12 1:02:09/

总目录
C# 语法总目录

C# 语法中级

  • lambda 表达式
    • 1. 捕获外部变量
    • 2. 捕获迭代变量
  • 匿名类型
  • 匿名方法
  • 异常相关
    • 1. 枚举器
    • 2. 可枚举对象
    • 3. 迭代器
    • 3. 迭代器语义
    • 4. yield break 语句
    • 5. 组合序列
  • 可空类型
    • 1. Nullable< T > 结构体

lambda 表达式

编译器在内部将lambda表达式编译为一个私有方法,并将表达式代码转移到该方法中。

1. 捕获外部变量

lambda表达式可以引用方法内定义的局部变量和方法的参数

捕获的变量在真正调用委托时赋值,而不是在捕获时赋值

c#">static void Main(string[] args)
{int num = 2;Func<int, int> multi = n => n * num;Console.WriteLine(multi(3));        //6num = 10;//调用时才给捕获变量赋值Console.WriteLine(multi(3));        //30
}

2. 捕获迭代变量

捕获迭代变量时因为捕获的是同一个变量,值变,地址却没变。又有捕获变量是调用时才赋值,所以在迭代完成后,输出的都是一样的值。

c#">Action[] actions = new Action[3];
for (int i = 0; i < actions.Length; i++)
{actions[i] = () => Console.Write(i);
}
foreach (Action a in actions)
{a();
}
//输出 333//如果想获取迭代时的值,那么有这么几种方式
//方式1 获取后立马调用
Action[] actions = new Action[3];
for (int i = 0; i < actions.Length; i++)
{actions[i] = () => Console.Write(i);actions[i]();    //输出012
}    
//方式2 使用局部变量,保存的每个值地址都不一样,不是同一个变量
Action[] actions = new Action[3];
for (int i = 0; i < actions.Length; i++)
{//局部变量int num = i;actions[i] = () => Console.Write(num);
}
foreach (Action a in actions)
{a();        //输出  012
}

匿名类型

c#">var person = new {Name="lisi",Age=18};//或者
int age = 18;
var person = new {Name="lisi",Age = age};
var person1 = new {Name="zhangsan",Age = "20"};
Console.WriteLine(person.GetType()==person1.GetType());        //True

匿名方法

匿名方法

c#">delegate int Transformer(int i);
static void Main(string[] args)
{Transformer sqr = delegate (int x) { return x * x; };Console.WriteLine(sqr(3));Console.ReadLine();
}
//9

异常相关

常见异常

c#">System.ArgumentException;           //参数异常
System.ArgumentNullException;       //空参数异常
System.ArgumentOutOfRangeException; //参数超过范围
System.InvalidOperationException;   //方法执行失败
System.NotSupportedException;       //不支持特定的功能异常
System.NotImplementedException;     //未实现异常
System.NullReferenceException;      //空参数异常

try…catch…finally语句

c#">try
{}
catch (Exception e)
{}
finally
{}

枚举器和迭代器

1. 枚举器

枚举器(Enumerator)是一个只读的且只能在值序列上前移的游标。

任何具有MoveNext方法和Current属性的对象都被称作枚举器。

枚举器实现了下面的接口之一:

  • System.Collections.IEnumerator

  • System.Collections.Generic.IEnumerator

2. 可枚举对象

可枚举对象(Enumerable),它可以生成枚举器。

可枚举的对象可以是:

  • IEnumerable 或 IEnumerable的实现。

  • 具有名为GetEnumerator 的方法并且返回值是一个枚举器 (Enumerator)对象

注意:IEnumerator 和 IEnumerable 定义在 System.Collections 里。

​ IEnumerator 和 IEnumerable 定义在 System.Collections.Generic 里。

c#">//枚举器模板
class Enumerator
{public IteratorVariableType Current{ get{...}}public bool MoveNext(){...}
}
//可枚举类型模版
class Enumerable
{public Enumerator GetEnumerator(){...}
}

3. 迭代器

迭代器是枚举器的生产者。foreach语句是枚举器的消费者。

案例:使用迭代器来返回斐波那契数列(每个数字是前两个数字之和)

c#">using System;
using System.Collections.Generic;
class Test
{static void Main(){foreach(int fib in Fibs(6))Console.Write(fib+" ");}//迭代器方法static IEnumerable<int> Fibs(int fibCount){for(int i =0,prevFib =1,curFib=1;i<fibCount;i++){yield return prevFib;int newFib = prevFib+curFib;prevFib = curFib;curFib = newFib;}}
}//输出
1 1 2 3 5 8

3. 迭代器语义

迭代器是包含一个或者多个 yield 语句的方法,属性或者索引器。

c#">//迭代器必须返回以下四个接口之一(否则编译器会产生相应错误):
//可枚举接口
System.Collections.IEnumerable
System.Collections.Generic.IEnumerable<T>//枚举器接口
System.Collections.IEnumerator
System.Collections.Generic.IEnumerator<T>//多个yield语句
class Test
{static void Main(){foreach(string s in Foo())Console.WriteLine(s);    //输出 One,Two,Three}static IEnumerable<string> Foo(){yield return "One";yield return "Two";yield return "Three";}
}

4. yield break 语句

yield break 语句表明迭代器块不再返回更多的元素,而是提前退出。

c#">static IEnumerable<string> Foo(bool breakEarly)
{yield return "One";yield return "Two";if(breakEarly)yield break;            //到这里就退出了yield return "Three";
}

注意:yield return 语句不能出现在 try…catch…finally 块中,只能出现在try…finally中try块里面。

通常使用foreach或隐式销毁枚举器,但是如果显示使用枚举器,提前结束枚举而不销毁枚举器,绕过了finally块的执行。那么我们可以将枚举器显式包裹在using语句中来避免上述错误。

c#">string firstElement = null;
var sequence = Foo();
using(var enumerator = sequence.GetEnumerator())    //使用using,会自动关闭一个持续流if(enumerator.MoveNext())firstElement = enumerator.Current;

5. 组合序列

迭代器有高度可组合性。迭代器模式的组合对LINQ非常重要。

c#">class Program
{static void Main(string[] args){foreach (int fib in EvenNumbersOnly(Fibs(6))){Console.WriteLine(fib);}}static IEnumerable<int> Fibs(int fibCount){for (int i = 0,prevFib = 1,curFib =1;  i<fibCount; i++){yield return prevFib;int newFib = prevFib + curFib;prevFib = curFib;curFib = newFib;}}static IEnumerable<int> EvenNumbersOnly(IEnumerable<int> sequence){foreach (int x in sequence){if ((x % 2) ==0){yield return x;}}}
}

可空类型

可空类型必须要在数据类型后加一个 ? 表示

c#">string s = null; //不报错,引用类型可以为null
int i = null;    //报错,值类型不能为null//如果想要一个值类型表示null,那么必须要用可空类型
//可空类型是由数据类型后加一个?来表示
int? i = null;
Console.WriteLine(i==null);    //输出 True

1. Nullable< T > 结构体

上面案例中的 int? 会被编译为 System.Nullable< T >,它是一个轻量级的不可变的结构体。它只有两个字段,分别代表Value和HasValue。

c#">public struct Nullable<T> where T : struct
{public T Value {get;}public bool HasValue {get;}public T GetValueOrDefault();public T GetValueOrDefault(T defaultValue);...
}//因此
int? i =null;
Console.WriteLine(i == null);    //True//等价于Nullable<int> i = new Nullable<int>();
Console.WriteLine(!i.HasValue);    //True

总目录
C# 语法总目录


http://www.ppmy.cn/server/157621.html

相关文章

迭代器 - 迭代器的概念及使用方法

在C中&#xff0c;迭代器&#xff08;Iterator&#xff09;是一种用于遍历容器&#xff08;如std::vector、std::list、std::map等&#xff09;中元素的对象。迭代器提供了一种统一的方式来访问容器中的元素&#xff0c;而不需要关心容器的具体实现细节。本文将详细介绍迭代器的…

LabVIEW数据库管理系统

LabVIEW数据库管理系统&#xff08;DBMS&#xff09;是一种集成了数据库技术与数据采集、控制系统的解决方案。通过LabVIEW的强大图形化编程环境&#xff0c;结合数据库的高效数据存储与管理能力&#xff0c;开发人员可以实现高效的数据交互、存储、查询、更新和报告生成。LabV…

大语言模型提示技巧(七)-扩展

扩展是将较短的文本&#xff0c;例如一组提示或主题列表&#xff0c;输入到大型语言模型中&#xff0c;让模型生成更长的文本。我们可以利用这个特性让大语言模型生成基于某个主题的电子邮件或小论文。通过这种方式使用大语言模型&#xff0c;可以为工作与生活提供诸多便利&…

文件或目录损坏且无法读取:深度解析与实战恢复指南

一、现象直击&#xff1a;文件或目录损坏的困扰 在日常的数字生活中&#xff0c;我们时常会遭遇一个令人头疼的问题——文件或目录损坏且无法读取。这一提示如同电脑世界中的红色警报&#xff0c;让我们的重要资料瞬间变得遥不可及。无论是工作文档、学习笔记&#xff0c;还是…

HarmonyOS开发:传参方式

一、父子组件传参 1、父传子&#xff08;Prop方式&#xff09; 父组件代码 Entry Component struct ParentComponent {State parentMessage: string Hello from Parent;build() {Column() {ChildComponent({ message: this.parentMessage });}} } 子组件代码 Component s…

缓存常见问题

缓存问题&#xff1a; 1. 缓存穿透&#xff1a;访问一个不存在的缓存 2. 缓存击穿&#xff1a;大批用户访问热点数据的时候&#xff0c;热点数据缓存失效&#xff0c;大量访问数据库 3. 缓存雪崩&#xff1a;大批量缓存全部失效 Redis和Memcached区别&#xff1a; 1. Redi…

【YOLOv8杂草作物目标检测】

YOLOv8杂草目标检测 算法介绍模型和数据集下载 算法介绍 YOLOv8在禾本科杂草目标检测方面有显著的应用和效果。以下是一些关键信息的总结&#xff1a; 农作物幼苗与杂草检测系统&#xff1a;基于YOLOv8深度学习框架&#xff0c;通过2822张图片训练了一个目标检测模型&#xff…

mv指令详解

&#x1f3dd;️专栏&#xff1a;计算机操作系统 &#x1f305;主页&#xff1a;猫咪-9527-CSDN博客 “欲穷千里目&#xff0c;更上一层楼。会当凌绝顶&#xff0c;一览众山小。” 目录 基本语法 主要功能 常用选项详解 1. 移动文件或目录 2. 重命名文件或目录 3. -i&am…