C# 知识点总结

入门

C#程序在.NET上运行,.NET framework包含两个部分:
①:.NET framework类库
②:公共语言运行库CLR(.NET虚拟机)
CLS(公共语言规范) CTS(通用类型系统)
.NET 还包含大量库,这些库支持多种不同的工作负载。

编译工具:

使用visual studio code 新建控制台,进入终端(Ctrl+~),选择好文件存储位置之后,输入dotnet命令即可;

dotnet new console  //新建控制台应用

使用visual studio 2022 新建项目,选择控制台(.NET Framwork);

using System;
class Program 
{ static void Main() { Console.WriteLine("Hello, World!");         }  
}

请看大屏幕,程序员入门之向世界说你好,
Main静态方法是C#程序的入口点。

所有代码都必须包含在类中,类的文件后缀名为.cs,最上面是using,然后是命名空间→类→属性和方法→代码块;

数据类型

C#中有两大类,值类型和引用类型

值类型

包含数据的实际值,而不是引用。类似于Java中的四类八种,这里就不一一例举了,可以百度下。

引用类型

存储了一个指向对象的引用,包括常见的类、字符串、数组、接口、委托、Null,dynamic等。

类型判断

使用var关键字,可以根据变量的初始化值"推断"变量的类型。

例如:

var a=0;
就变成
int a=0;

var定义的类型是静态的,在编译时候就被定义好了。

而dynamic定义的是动态类型,它在程序运行的时候才会确定。

值类型(Value Types)和引用类型(Reference Types)的区别

值类型:

1.直接存储数据的实际值,存储在栈(Stack)中,且内存分配和释放是⾃动完成的。每个值类型的变量都具有⾃⼰的内存空间,互相独⽴。

2.当⼀个值类型的变量被赋值给另⼀个变量,实际上是将该值的副本复制给了新变量。因此,修改⼀个变量不会影响到其他变量,它们互相独⽴。(纸张的复印,修改复印件不会影响本件)。

3.当将值类型的变量作为⽅法的参数进⾏传递时,实际上是将值的副本传递给了⽅法。在⽅法内部对参数的修改不会影响到原始变量。

4.值类型适⽤于较⼩的简单数据,具有快速的访问和复制特性。

引用类型:

1.存储的事对象的引用,也就是内存地址,对象本身存储在堆(Heap)中,多个引⽤类型的变量可以指向同⼀个对象,它们共享同⼀块内存空间。

2.当⼀个引⽤类型的变量被赋值给另⼀个变量,实际上是将对象的引⽤复制给了新变量。因此,两个变量引⽤同⼀个对象,修改其中⼀个变量会影响到另⼀个变量,它们共享同⼀块内存空间。(同⼀个云盘资源,使⽤不同链接分享给不同的⼈时,⼤家看到的资源是同⼀个资源,如果这个资源被修改了,⼤家看到的都变化了)。

3.当将引⽤类型的变量作为⽅法的参数进⾏传递时,实际上是将对象的引⽤传递给了⽅法。在⽅法内部对参数引⽤的对象进⾏的修改会影响到原始变量。

4.引⽤类型适⽤于复杂的对象、⼤型数据集合和需要共享数据的场景,但需要更多的内存开销和额外的访问层级。

装箱和拆箱

装箱和拆箱的过程就是将值类型和引用类型互相转换的过程,但是实际开发中尽量避免出现装箱和拆箱,为什么?因为损耗性能,可以使用泛型来避免。

//装箱
int number=20;
object obj=number;
//拆箱
int numberss=(int)obj;

运算符

这里也不一一介绍了,所有开发语言的运算符基本一致,极个别除外;

运算法优先级

优先级简易概括:有括号先括号,后乘除在加减,然后位移再关系,逻辑完后条件,最后⼀个逗号,。

字符串处理

字符串拼接

常规字符串处理就是定义两个string,然后拼接;

string firstName = "Taylor";string lastName = "Swift";Console.WriteLine(firstName + lastName);
//输出TaylorSwift

但是有没有想过,如果N个字符拼接呢,要写N个?那么性能呢?C#中为了提高程序性能,提供了StringBuilder方法进行拼接。

StringBuilder btf = new SreingBuilder();btf.Append("Taylor");btf.Append("Swift");Console.WriteLine(btf);
//输出TaylorSwift

字符串格式化

string.Format:

string firstName = "Taylor";string lastName = "Swift";string result = string.Format("first name is {0}, last name is {1}", firstName, lastName); Console.WriteLine(result);
//输出TaylorSwift

 交互

输出用WriteLine,输入呢?ReadLine。

string btf = Console.ReadLine();Console.WriteLine(btf);

 分支和循环

分支

if、if else if、switch分支

分支同Java、Python、Shell一样的。

循环

for、foreach、while、do...while循环

循环也是,foreach循环式当做集合使用(个人理解)和for没有什么区别

int[] arr = {1,2,3,4,5};foreach (int var in arr)
{Console.WriteLine(var);
}

 枚举

枚举是值类型C#中,不能被继承

//定义枚举DayofWeek 
enum DayofWeek{Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday}static void Main() { Console.WriteLine("Day of the week: " + DayofWeek.Monday);        }  

还有一种调用,如果报错因为层级的关系将实例化放在枚举上边即可。

 enum DayofWeek{Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday}DayofWeek DayofWeekEnum = DayofWeek.Monday;

 结构体

public struct Person
{//定义两个字段public string Name;public int Age;
} static void Main(string[] args) {Person person = new Person();//实例化
//赋值person.Name = "test";person.Age = 18;
//打印Console.WriteLine(person.Name);Console.WriteLine(person.Age);}    

 结构的特点:

结构可带有⽅法、字段、索引、属性、运算符⽅法和事件。

结构可定义构造函数,但不能定义析构函数。但是,不能为结构定义⽆参构造函数。⽆参构造函数(默认)是⾃动定义的,且不能被改变。

结构不能作为其他结构或类的基础结构。结构可实现⼀个或多个接⼝。结构成员不能指定为abstract、virtual或protected。当使⽤New操作符创建⼀个结构对象时,会调⽤适当的构造函数来创建结构。与类不同,结构可以不使⽤ New操作符即可被实例化。如果不使⽤New操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使⽤。

方法

功能:

代码重用

调用:类的实例.⽅法名([参数列表])静态⽅法:类名.⽅法名([参数列表])

方法分为有参和无参

static void Main() {代码块}
//Main方法(无参)static void Main(){
static void Ma(int a,int b) {Console.WriteLine($"{a},{b}");
}    int c =10;int d=20;Ma(c,d);
}
//有参

 异常处理

和Java、Python中的异常一样,try final finally

C#中 try、catch、finally、throw

try:⼀个try块标识了⼀个将被激活的特定的异常的代码块。后跟⼀个或多个catch块。

catch:程序通过异常处理程序捕获异常。catch关键字表⽰异常的捕获。

finally:finally块⽤于执⾏给定的语句,不管异常是否被抛出都会执⾏。例如,如果您打开⼀个⽂件,不管是否出现异常⽂件都要被关闭。

throw:当问题出现时,程序抛出⼀个异常。使⽤ throw 关键字来完成。

try
{一起异常的语句}
catch(异常(Exception(异常基类)) e)
{处理异常}
finally
{执行语句代码块}

*面向对象* 

面向对象是一种编程范式,使程序更加灵活,容易修改,易于复⽤。

它将现实世界的概念和实体表⽰为程序中的对象。

在⾯向对象编程中,程序由⼀组相互作⽤的对象组成,每个对象都有⾃⼰的状态(属性)和⾏为(⽅法)。

⾯向对象编程的核⼼思想是将复杂的问题分解为⼀系列相对独⽴的对象,这些对象通过相互发送消息来协同⼯作。

每个对象都可以封装⾃⼰的数据和功能,并且可以与其他对象进⾏交互。

1.类(Class):类是对象的模板或蓝图,描述了对象的属性和⽅法。它定义了对象的结构和⾏为。

2.对象(Object):对象是类的实例。每个对象都有⾃⼰的状态和⾏为。

.3封装(Encapsulation):封装是⼀种将数据和⽅法组合在⼀起的机制,以限制对对象内部数据的直接访问。通过封装,对象的内部细节对外部是隐藏的,只能通过对象的公共接⼜访问。

4.继承(Inheritance):继承是⼀种机制,允许创建⼀个新类(⼦类)来继承现有类(⽗类)的属性和⽅法。⼦类可以重⽤⽗类的代码,并可以在不修改⽗类的情况下扩展其功能。

5.多态(Polymorphism):多态允许以统⼀的⽅式使⽤不同类的对象。它使得可以在⽗类的引⽤下操作⼦类的对象,通过⽅法的重写和⽅法的重载实现多态性。

类的定义是以关键字class开始,后跟类的名称。类的主体,包含在⼀对花括号内。 (使用.访问类的成员)。

访问修饰符

1.public:公共访问修饰符,表⽰成员可以从任何地⽅访问,没有限制。

2.private:私有访问修饰符,表⽰成员只能在同⼀类中访问,对外部代码不可⻅。3.protected:受保护访问修饰符,表⽰成员可以在同⼀类内部和派⽣类中访问,对外部代码不可⻅。

4.internal:内部访问修饰符,表⽰成员可以在同⼀程序集中访问。程序集是指⼀组相关的代码⽂件(通常是⼀个项⽬或⼀个库),可以是单个项⽬或多个项⽬组成。5.protectedinternal:受保护内部访问修饰符,表⽰成员可以在同⼀程序集内和派⽣类中访问。这是protected和internal的组合,提供了更⼤的访问范围。

字段

在C#中,字段(Fields)是类中⽤于存储数据的成员,可以是公共的(public)、私有的(private)或受保护的(protected)。字段存储对象的状态和数据,并且可以通过类的实例进⾏访问和操作。

属性      

在C#中,属性(Properties)提供了对私有字段的访问,并允许控制对字段的访问⽅式。属性可以⽤于获取(get)和设置(set)字段的值,并且可以在访问时执⾏其他逻辑。

public static void ClassName
{private int age;public int Age{get{return age;}set{age = value;}}
}

字段和属性的区别

字段

字段可以直接访问,不受限制,无法对字段读写进行额外控制。

字段是类的成员变量。

字段只提供了简单的数据存储功能。

属性

属性通过访问器来访问(get和set),可以自定义读写逻辑。

属性可以封装字段。

属性的功能更加灵活。

构造函数

是一种特殊的方法。

构造函数可以有多个重载,每个重载可以接受不同类型和数量的参数,以满⾜不同的初始化需求。

使用构造函数的时候必须实例化(new)关键字。

构造函数在对象创建的过程中⾃动调⽤,⽤于执⾏初始化操作。可以在构造函数中设置字段的初始值、执⾏其他必要的操作,或者调⽤其他⽅法来完成初始化过程。

事件

是⼀种⽤于实现发布者-订阅者模式的机制,⽤于在对象之间传递消息和通知。事件允许⼀个对象(称为发布者)触发事件,并允许其他对象(称为订阅者)注册为事件的观察者,以便在事件发⽣时接收通知并执⾏相应的操作。

 public event EventHandler Work;public void onWork(){ Work.Invoke(this, EventArgs.Empty); }//事件触发static void Main(string[] args) { //实例化Program p = new Program();//订阅事件p.Work += Program.Working;//触发事件p.onWork();}//事件public static void Working(object sender, EventArgs e){Console.WriteLine("正在工作");}

索引器

 private int[] arr = new int[10];public int this[int index]{ get { return arr[index]; } set { arr[index] = value; }}static void Main(string[] args) { Program p = new Program();p[0] = 10;p[1] = 20;Console.WriteLine(p[0]);Console.WriteLine(p[1]);}

面向对象三大特性

封装

封装的意义在于保护或者防⽌代码(数据)被我们⽆意中破坏。

适当的封装可以让程式码更容易理解与维护,进⽽增强数据的安全性和简化程序的编写⼯作。

封装既可以封装成员变量,⼜可以封装成员⽅法(或属性)

static void Main() { Console.WriteLine("Hello, World!");Console.WriteLine("Hello, World!1");Console.WriteLine("Hello, World!2");Console.WriteLine("Hello, World!3");}

继承

继承是⾯向对象程序设计中最重要的概念之⼀。

继承→根据⼀个现有类来定义新类

好处:使得创建和维护应⽤程序变得更容易;

也有利于重⽤代码和节省开发时间。当创建⼀个新类时,如果这个类的某些成员和⼀个现有类相同。程序员不需要完全重新编写新的数据成员和成员函数,只需要创建⼀个新的类,继承这个现有类即可。这个已有的类被称为的基类,这个新的类被称为派⽣类。

class program:(继承的类)

多态

多态是同⼀个⾏为具有多个不同表现形式或形态的能⼒。

通俗地说:同⼀操作作⽤于不同的对象,产⽣不同的结果。

在C#中,每个类型都是多态的,因为包括⽤户定义类型在内的所有类型都继承⾃Object。

using System;class Program 
{public interface IWorker
{void Work();
}public class Engineer : IWorker
{public void Work(){Console.WriteLine("Engineer is working on a project.");}
}public class Designer : IWorker
{public void Work(){Console.WriteLine("Designer is working on a design.");}
}public class Manager
{private IWorker worker;public Manager(IWorker worker){this.worker = worker;}public void AssignWork(){worker.Work();}
}public static void Main(string[] args){Engineer engineer = new Engineer();Designer designer = new Designer();Manager manager = new Manager(engineer);manager.AssignWork();  // 输出: Engineer is working on a project.manager = new Manager(designer);manager.AssignWork();  // 输出: Designer is working on a design.}
}

 在C#中,多态性是指同一个接口可以被不同的类实现,从而允许这些类以不同的方式响应相同的消息。多态性通常通过继承和接口来实现。下面是一个简单的例子,展示了如何使用继承和接口来实现多态性。

首先,定义一个接口`IWorker`:
public interface IWorker
{
    void Work();
}
 

然后,定义两个类`Engineer`和`Designer`,它们都实现了`IWorker`接口:


public class Engineer : IWorker
{
    public void Work()
    {
        Console.WriteLine("Engineer is working on a project.");
    }
}

public class Designer : IWorker
{
    public void Work()
    {
        Console.WriteLine("Designer is working on a design.");
    }
}
 

接下来,定义一个`Manager`类,它包含一个`IWorker`类型的成员变量,并使用多态性来调用`Work`方法:


public class Manager
{
    private IWorker worker;

    public Manager(IWorker worker)
    {
        this.worker = worker;
    }

    public void AssignWork()
    {
        worker.Work();
    }
}
 

最后,在`Main`方法中演示多态性的使用:


public class Program
{
    public static void Main(string[] args)
    {
        Engineer engineer = new Engineer();
        Designer designer = new Designer();

        Manager manager = new Manager(engineer);
        manager.AssignWork();  // 输出: Engineer is working on a project.

        manager = new Manager(designer);
        manager.AssignWork();  // 输出: Designer is working on a design.
    }
}

在这个例子中,`Manager`类通过`IWorker`接口与`Engineer`和`Designer`类进行交互,而不需要知道具体是哪种类型的对象。这就是多态性的体现,它允许`Manager`类以统一的方式处理不同类型的`IWorker`对象。

多态性分为两种:

静态多态

动态多态

静态多态

根据传递的参数、返回类型等决定执⾏的操作⽅法重载——同⼀个范围内对相同的函数名有多个定义。参数列表个数或者类型不同。

动态多态

直到系统运⾏时,才决定实现何种操作通过抽象⽅法和虚⽅法实现的。

虚拟

当一个方法使用virtual修饰的时候,代表是虚方法,可以override重写子类。

注意:相同的方法以及参数列表

密封

当对⼀个类应⽤sealed修饰符时,此修饰符会阻⽌其他类从该类继承。

new:继承类中的⼀个⽅法“隐藏”基类中同名的⽅法。它会取代原⽅法,⽽不是覆盖。

抽象类

关键字abstract创建抽象类。当⼀个派⽣类继承⾃该抽象类时,必须实现该抽象类中的抽象⽅法。抽象类的⼀些规则:

不能直接创建⼀个抽象类的实例。

不能在⼀个抽象类外部声明⼀个抽象⽅法。

抽象类不能被声明为sealed。

抽象类可以包含抽象⽅法,抽象⽅法可被派⽣类实现。

抽象类可以定义普通⽅法、虚⽅法,并可以有实现。

 在C#中,抽象类是一种特殊的类,它不能被实例化,只能被继承。抽象类可以包含抽象方法和非抽象方法。抽象方法是一种没有实现的方法,必须在派生类中实现。下面是一个简单的例子,展示了如何使用抽象类。

using System;public abstract class Animal
{public abstract void MakeSound();public void Sleep(){Console.WriteLine("The animal is sleeping.");}
}public class Dog : Animal
{public override void MakeSound(){Console.WriteLine("The dog barks.");}
}public class Cat : Animal
{public override void MakeSound(){Console.WriteLine("The cat meows.");}
}public class Program
{public static void Main(string[] args){Animal myDog = new Dog();myDog.MakeSound();  // 输出: The dog barks.myDog.Sleep();      // 输出: The animal is sleeping.Animal myCat = new Cat();myCat.MakeSound();  // 输出: The cat meows.myCat.Sleep();      // 输出: The animal is sleeping.}
}

Animal类是一个抽象类,它包含一个抽象方法MakeSound和一个非抽象方法SleepDogCat类继承自Animal类,并实现了MakeSound方法。通过创建Animal类型的引用,可以调用MakeSound方法,而不需要知道具体是哪种类型的对象。这就是抽象类的使用,它允许我们以统一的方式处理不同类型的对象。

接口

接⼝本⾝并不实现任何功能,它只是和声明实现该接⼜的对象订⽴⼀个必须实现哪些⾏为的契约。

关于接口的定义请看多态的代码定义即可。

public interface inter
{void work();   
}

数组

简单数组

在声明数组时,应先定义数组中元素的类型,其后是⼀对空⽅括号和⼀个变量名。例如,下⾯声明了⼀个包含整型元素的数组∶

int[] myArray;

数组初始化

声明了数组后,就必须为数组分配内存,以保存数组的所有元素。数组是引⽤类型,所以必须给它分配堆上的内存。 

int[] myArray = new int[5];string[] stringArray = {1,2,3,4,5};//不同数组初始化

访问数组

在声明和初始化数组后,就可以使⽤索引器访问其中的元素了。数组只⽀持有整型参数的索引器,引用的用get、set。

int[] myArray = {1,2,3,4,5};int a = myArray[0]; //--1int b = myArray[3]; //--4//如果是复制过来的数组不知道元素个数,可以使用for/foreach遍历;
for(int i=0;i<myArray.Length;i++)
{Console.WriteLine(myArray[i]);
}foreach(int var in myArray)
{Console.WriteLine(var);
}

多维数据

多维数组⽤两个或多个整数来索引。

在C#中声明这个⼆维数组,需要在⽅括号中加上⼀个逗号。数组在初始化时应指定每⼀维的⼤⼩(也称为阶)。接着,就可以使⽤两个整数作为索引器来访问数组中的元素∶

int[,] one = new int[3,3];one[0,0] = 1;
//以此类推int[,] two = {{1,2,3},{4,5,6},{7,8,9}};//三维数组
int[,,] three = {{{1,2},{3,4}},{{5,6},{7,8}},{{9,0},{11,12}}};
Console.WriteLine(three[1,1,1]); //8
Console.WriteLine(three[0,1,1]); //4

锯齿数据

如果说一/二/三维数字式1*1/2*2/3*3,那么锯齿数据就是不规则的。

 int[][] ints = new int[3][];ints[0] = new int[2] { 1, 2 };ints[1] = new int[3] { 3,4,5 };ints[2] = new int[5] { 6,7,8,9,0 };for(int i = 0; i < ints.Length; i++){for(int j = 0; j < ints[i].Length; j++){Console.WriteLine($"i:{i},j:{j},value:{ints[i][j]}");}}

复制数组

    int[] intCopyArrayOne = {1,2,3};int[] intCopyArrayTwo = (int[])intCopyArrayOne.Clone();intCopyArrayTwo[0] = 100;Console.WriteLine(intCopyArrayOne[0]); //输出1Console.WriteLine(intCopyArrayTwo[0]); //输出100Console.WriteLine(intCopyArrayOne[1]); //输出2Console.WriteLine(intCopyArrayTwo[1]); //输出2Console.WriteLine(intCopyArrayOne[2]); //输出3Console.WriteLine(intCopyArrayTwo[2]); //输出3Console.WriteLine(intCopyArrayOne.Length); //输出3Console.WriteLine(intCopyArrayTwo.Length); //输出3Console.WriteLine(intCopyArrayOne == intCopyArrayTwo); //输出False

排序

string[] names = { "dog", "cat", "pig", "cow" };Array.Sort(names);foreach (string name in names) {Console.WriteLine(name);}

集合

List是与数组相当的集合类。.NETFramework为动态列表提供了泛型类List。这个类实现了IList、ICollection、Emumerable、List<ICollection和IEnumerable接⼝。

List<int> intList = new List<int>(){1,2,3};List<string> stringList = new List<string>(){"One","Two","Three"};//添加元素有Add
intList.Add(4);stringList.Add("Four");//Add只能单个添加,AddRange()批量添加;intList.AddRange(new int[]{4,5,6});stringList.AddRange(new string[]{"Four","Five","Sex"});//添加元素InsertstringList.Insert(3,"aaa");//访问元素 可以根据索引或者循环string num = stringList[3];for(int i=0;i<intList.Length;i++)
{Console.WriteLine(intList[i])
}//删除元素
//RemoveAt 根据索引删除
stringList.RemoveAt(5);
//Remove 删除指定元素
stringList.Remove("three");
//RemoveRange 批量删除
stringList.RemoveRange(3,3);//查找元素
int strListIndex = stringList.IndexOf("Two");
Console.WriteLine(strListIndex);Console.WriteLine(intList.Find(x => x>5));//查找大于5Console.WriteLine(intList.FindIndex(x => x>5));//查找大于5索引Console.WriteLine(intList.FindAll(x => x>5));//查询所有大于5//排序--Sort 快速排序List<int> intList2 = new List<int>(){3,5,0};intList2.Sort();
foreach(var item in intList2)
{Console.WriteLine(item);
}//②
List<Person> pList = new List<Person>(){new Person("Aa","Aa"),new Person("Zz","Zz"),};pList.Sort();foreach(var item in pList)
{Console.WriteLine(item);
}

集合初始值设定项只能在声明集合时使⽤。AddRange()⽅法则可以在初始化集合后调⽤。如果在创建集合后动态获取数据,就需要调⽤AddRange0。

泛型

在C#中,泛型是⼀种参数化类型的机制,它允许在定义类、结构、接⼜和⽅法时使⽤类型参数。使⽤泛型可以创建可以在多个数据类型上⼯作的通⽤代码,⽽不需要针对每种具体类型编写重复的代码。泛型的主要优势是提⾼了代码的可重⽤性、类型安全性和性能。通过使⽤泛型,可以编写更加灵活和通⽤的代码,同时在编译时进⾏类型检查,避免在运⾏时出现类型错误。

using System;/// <summary>
/// Box<T>是一个泛型类,它使用类型参数T来表示内容类型。
/// SetContent和GetContent方法都是泛型方法,它们接受和返回类型为T的参数。
/// 在Main方法中,创建了Box<int>和Box<string>的实例,并分别设置了整数和字符串内容。
/// 通过使用泛型,我们可以在不牺牲类型安全的情况下,创建可以处理不同数据类型的通用组件。
/// </summary>
/// <typeparam name="T"></typeparam>
public class Box<T>
{private T content;public void SetContent(T content){this.content = content;}public T GetContent(){return content;}
}
public class Program
{public static void Main(string[] args){Box<int> intBox = new Box<int>();intBox.SetContent(10);Console.WriteLine(intBox.GetContent());  // 输出: 10Box<string> stringBox = new Box<string>();stringBox.SetContent("Hello, World!");Console.WriteLine(stringBox.GetContent());  // 输出: Hello, World!}
}

委托

在C#中,委托(Delegate)是⼀种类型,它允许您将⽅法作为参数传递,并在需要时调⽤该⽅法。委托可以⽤于声明⽅法的签名,并且可以创建对符合该签名的任何⽅法的引⽤。委托可⽤于实现事件和回调机制,使得代码更加灵活和可扩展。它提供了⼀种在运⾏时动态决定要调⽤的⽅法的⽅式,这对于处理异步操作、事件处理程序和回调函数⾮常有⽤。

using System;/// <summary>
/// Action是一个委托,它定义了一个没有参数且没有返回值的方法签名。
/// SayHello方法与Action委托的签名兼容,因此我们可以创建一个Action委托的实例,
/// 并将SayHello方法赋值给它。然后,我们可以通过调用action来执行SayHello方法。
/// </summary>public delegate void Action();public class Program{public static void Main(string[] args){Action action = new Action(SayHello);action();  // 输出: Hello, World!void SayHello(){Console.WriteLine("Hello, World!");}}}/// <summary>
/// 在这个例子中,ActionWithParam是一个委托,它定义了一个接受一个整数参数且没有返回值的方法签名。
/// PrintNumber方法与ActionWithParam委托的签名兼容,
/// 因此我们可以创建一个ActionWithParam委托的实例,并将PrintNumber方法赋值给它。
/// 然后,我们可以通过调用action并传递参数来执行PrintNumber方法。
/// </summary>
/// <param name="param"></param>
public delegate void ActionWithParam(int param);public class Program
{public static void Main(string[] args){ActionWithParam action = new ActionWithParam(PrintNumber);action(42);  // 输出: 42void PrintNumber(int number)
{Console.WriteLine(number);
}}
}

 

lambda/Linq

Lambda表达式是一种匿名函数,可以用于表示简单的函数逻辑。LINQ(Language Integrated Query)是一种查询语言,

1.基本语法:Lambda表达式由参数列表、箭头符号和表达式组成。

2.表达式体和语句体:允许在Lambda表达式中编写多个语句。

3.引⽤外部变量:Lambda表达式可以引⽤外部作⽤域中的变量。即闭包。

4.异步⽀持:async和await关键字,使得异步编程变得更加容易。Lambda表达式可以与异步⽅法⼀起使⽤,从⽽提供异步操作的简洁语法。

Lambda表达式的应⽤⾮常⼴泛:

1.LINQ查询:Lambda表达式可以作为LINQ查询的条件和投影函数,简化了对集合的筛选、排序和转换操作。

var result =collection.Where(x=>x>5).0rderBy(x => x).Select(x =>x);

2.委托和事件处理:Lambda表达式可以⽤于创建委托实例,或者作为事件处理程序。

Action<int>action=x=>Console.WriteLine(x);
button.Click +=(sender,e)=> Console.WriteLine("Button clicked");

3.并⾏编程:通过Parallel类和TaskParallelLibrary(TPL)等并⾏编程框架,Lambda表达式可以⽤于创建并⾏任务和线程。

Parallel.For(0,10,i=>Console.WriteLine(i));Task.Run(()=>{/* 任务代码 */});

4.表达式树:Lambda表达式可以被编译为表达式树,使得我们能够在运⾏时分析和操作代码。

using System;/// <summary>
/// 创建了一个Person对象的列表。
///使用Lambda表达式和LINQ查询来筛选年龄大于30的人。
///Lambda表达式p => p.Age > 30定义了一个匿名函数,
///它接受一个Person对象并返回一个布尔值,表示该对象的年龄是否大于30。
///LINQ查询from p in people where p.Age > 30 select p使用Where子句来筛选满足条件的对象,
///并使用Select子句来选择结果对象。最后,我们使用foreach循环来输出结果。
/// </summary>
public class Person
{public string Name { get; set; }public int Age { get; set; }
}public class Program
{public static void Main(string[] args){List<Person> people = new List<Person>{new Person { Name = "Alice", Age = 30 },new Person { Name = "Bob", Age = 25 },new Person { Name = "Charlie", Age = 35 }};// 使用Lambda表达式筛选年龄大于30的人var adults = people.Where(p => p.Age > 30);// 使用LINQ查询年龄大于30的人var adultsLinq = from p in peoplewhere p.Age > 30select p;// 输出结果foreach (var person in adults){Console.WriteLine($"{person.Name} is an adult.");}foreach (var person in adultsLinq){Console.WriteLine($"{person.Name} is an adult.");}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/49706.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【分布式系统】 单机架构 | 分布式架构 | 集群 | 主从架构 | 分库分表 | 冷热分离 | 微服务

文章目录 [toc] 分布式系统一、单机架构二、分布式系统三、应用服务器集群四、读写分离 / 主从分离架构五、引入缓存/冷热分离架构六、垂直分库七、微服务架构——业务拆分代价优势 八、名词解释1.应用&#xff08;Application&#xff09;/系统(System)2.模块&#xff08;Mode…

Mysql9安装

目录 一、下载mysql 二、安装 三、配置mysql环境变量 四、mysql初始化和启动 1.以管理员身份运行cmd 2.cd到mysql的安装目录 3.初始化mysql的数据库 4.为Windows系统安装MySQL服务 5.查看一下名为mysql的服务&#xff1a; 6.启动MySQL服务 五、附录 1.系统变量还在&…

CentOS 8中 更新或下载时报错:为仓库 ‘appstream‘ 下载元数据失败 : Cannot prepare internal mirrorlist

一、错误重现 CentOS Stream 8 - AppStream 0.0 B/s | 0 B 00:00 Errors during downloading metadata for repository appstream: - Curl error (6): Couldnt resolve host name for http://mirrorlis…

昇思25天学习打卡营第18天|生成式-GAN图像生成

打卡 目录 打卡 GAN 博弈函数 博弈过程 GAN 案例 数据集 数据加载与可视化 隐码构造 模型构建 生成器 判别器 损失函数和优化器 模型训练 输出展示-1w张训练样本 输出展示-6w张训练样本 输出展示-6w张-100 epoch 效果展示 部分展示如图-12epoch-6w张 部分展…

Windows系统上Git详细图文安装及使用教程

Git 是一种高效、分布式的版本控制系统&#xff0c;用于代码的跟踪、分支管理和协同工作&#xff0c;支持快速提交、合并和回滚操作。它是开发者工具箱中必不可少的工具之一&#xff0c;广泛应用于软件开发和其他需要版本控制的领域。 1. Git的安装 1.1 Git下载 可以通过以下…

Qt SQLite数据库学习总结

到此为止&#xff0c;就使用Qt进行SQLite数据库的操作&#xff0c;做一次总结 1. Qt中数据库操作的相关概念和类 Qt 数据库编程相关基本概念https://blog.csdn.net/castlooo/article/details/140497177 2.表的只读查询--QSqlQueryModel QSqlQueryModel单表查询的使用总结htt…

微信小程序--点击按钮可新增可删除

案例: html: <view ><view ><view class="guzhang" wx:for="{{inputs}}" wx:key="id" wx:for-item="item" wx:for-index="index"><view class="huanhang"><view class="fontBo…

员工网络监控软件:把控员工网络活动的标尺

在竞争激烈的漩涡之中&#xff0c;企业如同一只不断旋转的陀螺&#xff0c;努力保持着自身的平衡和稳定&#xff0c;而员工的网络活动则是那无形却强大的力量&#xff0c;时刻影响着企业的运转。员工网络监控软件仿佛一根坚固无比的轴心&#xff0c;以其精准的标尺帮助企业实现…

Mindspore框架循环神经网络RNN模型实现情感分类|(六)模型加载和推理(情感分类模型资源下载)

Mindspore框架循环神经网络RNN模型实现情感分类 Mindspore框架循环神经网络RNN模型实现情感分类|&#xff08;一&#xff09;IMDB影评数据集准备 Mindspore框架循环神经网络RNN模型实现情感分类|&#xff08;二&#xff09;预训练词向量 Mindspore框架循环神经网络RNN模型实现…

顶级 Vue 管理仪表板和模板

Vue.js 是当今繁忙的 Web 开发领域中最受欢迎的 JavaScript 框架之一&#xff0c;用于创建交互式动态用户界面。Vue.js 的组件反应性及其流畅的数据绑定使其在管理仪表板设计方面占据了主导地位。 本文讨论了一些领先的 ​​Vue 管理员仪表板&#xff0c;它们可以节省您制作 We…

计算机网络之http和https的区别(外加http详解)

http协议和各种协议之间的关系 1、DNS解析&#xff0c;获取到访问服务器的IP 2、HTTP生成请求报文请求&#xff0c;请求访问页面资源 3、TCP协议将报文切割成一份一份报文段后&#xff0c;以可靠的方式进行传输 4、IP协议边搜索边中转&#xff0c;将这些数据包传输给接受方…

k8s 公共服务

修改named.conf。修改第13行和第21行 下面是 named.rfc1912 修改位置&#xff0c;在最后 所以用cp -p 复制文件&#xff0c;保留权限 nslookup 回车&#xff0c;server是看哪个dns 在起作用 dns服务器要配置给所有公共服务节点和 k8s 节点 就在网络文件加个DNS2就行了&…

CSS3雷达扫描效果

CSS3雷达扫描效果https://www.bootstrapmb.com/item/14840 要创建一个CSS3的雷达扫描效果&#xff0c;我们可以使用CSS的动画&#xff08;keyframes&#xff09;和transform属性。以下是一个简单的示例&#xff0c;展示了如何创建一个类似雷达扫描的动画效果&#xff1a; HTM…

docker笔记4-镜像理解

docker笔记4-镜像理解 一、镜像原理之联合文件系统二、镜像原理之分层理解三、commit镜像 一、镜像原理之联合文件系统 UnionFS&#xff08;联合文件系统&#xff09;: Union文件系统&#xff08;UnionFS&#xff09;是一种分层、轻量级并且高性能的文件系统&#xff0c;它支持…

vue2使用univerjs

1、univerjs Univer 提供了一个全面的企业级文档与数据协同的解决方案&#xff0c;支持电子表格、文本文档和演示幻灯片三大核心文档类型。通过灵活的 API 和插件机制&#xff0c;开发者可以在 Univer 的基础上进行个性化功能的定制和扩展&#xff0c;以适应不同用户在不同场景…

【JavaEE】Spring Boot 自动装配原理(源码分析)

一. 前言 我们在写Spring Boot的程序代码的时候, 可以注入很多我们没有定义过的Bean.例如: Autowired private ApplicationContext applicationContext; Autowired public DataSourceTransactionManager transactionManager; Autowired public AutowireCapableBeanFactory …

UnrealEngine摸索(一)——Static Mesh Actor不会阻挡可见性查询解决方法

实际开发中遇到题目所述的问题&#xff0c;对解决方法进行记录 文章目录 问题描述解决方案 问题描述 博主在开发FPS游戏过程中&#xff0c;使用 LineTraceSingleByChannel 进行可视性检测&#xff0c;即其参数 Channel Visiblity&#xff0c;对于命中的第一个物体应用相应的处…

《0基础》学习Python——第十八讲__爬虫/<1>

一、什么是爬虫 爬虫是一种网络数据抓取的技术。通过编写程序&#xff08;通常使用Python&#xff09;&#xff0c;爬虫可以自动化地访问网页&#xff0c;解析网页内容并提取出所需的数据。爬虫可以用于各种用途&#xff0c;如搜索引擎的索引&#xff0c;数据分析和挖掘&#x…

Vue 3项目安装Element-Plus

Element Plus 是一个基于 Vue 3 的现代前端UI框架&#xff0c;它旨在提升开发体验&#xff0c;并为开发者提供高效、优雅的组件。如果你正在使用 Vue 3 进行项目开发&#xff0c;那么安装和集成 Element Plus 是一个不错的选择。在本文中&#xff0c;博主将详细介绍如何在 Vue …

[嵌入式Linux]-常见编译框架与软件包组成

嵌入式常见编译框架与软件包组成 1.嵌入式开发准备工作 主芯片资料包括&#xff1a; 主芯片资料 主芯片开发参考手册&#xff1b;主芯片数据手册&#xff1b;主芯片规格书&#xff1b; 硬件参考 主芯片硬件设计参考资料&#xff1b;主芯片配套公板硬件工程&#xff1b; 软件…