首页 > 编程语言 >C# 语法中级

C# 语法中级

时间:2025-01-09 14:05:10浏览次数:3  
标签:中级 Console 迭代 C# System yield 语法 int 枚举

总目录
C# 语法总目录

C# 语法中级

lambda 表达式

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

1. 捕获外部变量

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

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

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

2. 捕获迭代变量

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

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
}

匿名类型

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

匿名方法

匿名方法

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

异常相关

常见异常

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

try…catch…finally语句

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 里。

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

3. 迭代器

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

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

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 语句的方法,属性或者索引器。

//迭代器必须返回以下四个接口之一(否则编译器会产生相应错误):
//可枚举接口
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 语句表明迭代器块不再返回更多的元素,而是提前退出。

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语句中来避免上述错误。

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

5. 组合序列

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

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;
            }
        }
    }
}

可空类型

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

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。

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# 语法总目录

标签:中级,Console,迭代,C#,System,yield,语法,int,枚举
From: https://blog.csdn.net/qq_44653106/article/details/137838689

相关文章

  • Eclipse 透视图
    透视图是一个包含一系列视图和内容编辑器的可视容器。默认的透视图叫java。Eclipse窗口可以打开多个透视图,但在同一时间只能有一个透视图处于激活状态。用户可以在两个透视图之间切换。操作透视图通过"Window"菜单并选择"OpenPerspective>Other"来打开透视图对话框。......
  • Eclipse 工作空间
    eclipse工作空间包含以下资源:项目文件文件夹项目启动时一般可以设置工作空间,你可以将其设置为默认工作空间,下次启动后无需再配置:工作空间(Workspace)有明显的层次结构。项目在最顶级,项目里头可以有文件和文件夹。插件可以通过资源插件提供的API来管理工作空间的资源。......
  • PCL点云库入门——PCL库点云特征之FPFH点快速特征直方图(Fast Point Feature Histogram
    1、FPFH原理        快速点特征直方图(FastPointFeatureHistograms,简称FPFH)是对PFH(PointFeatureHistograms)计算方法的一种简化,具体内容看参考十四节内容。该方法的核心在于独立计算查询点的K邻域内每个点的简化点特征直方图(SimplifiedPointFeatureHistogram,简......
  • 06、Docker学习,常用安装:Zookeeper、ES、Minio
    Docker学习,常用安装:Zookeeper、ES、Minio一、Docker安装Zookeeper##查询zookeeper镜像dockersearchzookeeper##拉去zookeeper镜像dockerpullzookeeper:latest##本地创建zookeeper的挂载目录mkdir-p/opt/software/myfile/zookeeper/confmkdir-p/opt/softwar......
  • 《前端技术基础》第02章 CSS基础【合集】
    目录......
  • 网络流量控制神器:深入理解 `tc` 命令及其实际应用
    网络流量控制神器:深入理解tc命令及其实际应用在现代互联网环境中,网络流量管理对系统稳定性和性能优化至关重要。作为Linux系统中强大的流量控制工具,tc(TrafficControl)为我们提供了对流量排队、限速、优先级管理等功能的全面控制。无论是开发测试还是生产环境下的性能调......
  • CDS标准视图:付款锁定原因描述 I_PaymentBlockingReasonText
    视图名称:付款锁定原因描述I_PaymentBlockingReasonText视图类型:基础视图代码:点击查看代码//Documentationaboutannotationscanbefoundathttp://help.sap.comsearchingforCDSannotations//InsertedbyVDMCDSSuitePlugin@ObjectModel.usageType.sizeCategory......
  • Linux TCP连接数查询
    netstat-anput2统计连接数2.1统计80端口的连接数netstat-nat|grep-i"80"|wc-l2.2统计总连接数netstat-nat|wc-l2.3统计已连接上的,状态为establishednetstat-na|grepESTABLISHED|wc-l3统计所有请求状态及数量netstat-an|awk'/^tcp/{++S[$NF]}END{for......
  • IIC的上拉电阻的设置需要考虑哪些因素
    在I²C(Inter-IntegratedCircuit)总线设计中,上拉电阻(Pull-upResistor)的设置非常重要,因为它直接影响总线的信号完整性、通信速度和功耗。以下是设置I²C上拉电阻时需要考虑的关键因素:1. 总线电容(BusCapacitance)总线电容的来源:PCB走线的寄生电容。连接设备的输入电容。......
  • VUE +WebSocket+speak-tt 实现在浏览器右下角实时给商家推送订单消息
    先看效果  1、WebSocket服务建立 1.1引入包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>1.2新建配置类packagecom......