CShape
VS保存为UTF-8:扩展——自定义——搜索ForceUTF8
VS帮助文档:
Visual Studio Installer——单个组件——Help Viewer
VS——帮助——添加和移除帮助内容——索引
C# 教程 | 菜鸟教程 (runoob.com)
一、入门 1 C#特点
命名方式:
变量前类型后名字,前小写后大写,例子:intNum,strClass
函数命名大写,属性命名小写。
Console.WriteLine(); float num = float .Parse(Console.ReadLine());Console.Write(); using namenamespace name {}class name {}void name {}Main(); #region MyRegion #endregion
2 VS操作
VS的自动补足中的含义(扳手:属性,方块:方法,长方体:字段)
Ctrl + A 全选
Ctrl + K + F 自动缩进
Ctrl + K + C 注释
Ctrl + K + U 取消注释
Ctrl + R + R 全体重命名
Ctrl + F:选择字符串替换
类中自动补足类中属性:tab + tab
二、类型 1 一般类型
详细文档
official::官方文档
N元运算符:几个变量参与运算:
一元运算符:i++
二元运算符: a+b
三元运算符:a?b:c
String str = string .Format("a:{0},b:{1}" ,a,b); char a = '\0' ;string a = "" ;x = int .Parse(a); x = a.ToString(); byte i4 = 300 ;int i3 = i4;int i4;byte i3 = (byte ) i4;byte b = 0 ;b += 3 ; b = b + 3 ; var v1;object o1 = 1 /true /new int [3 ];
2 特别类型 enum Directon:int {up,down} MyEnum enumValue = (MyEnum)Enum.Parse(typeof (MyEnum), str); int ? num = null ;num.Value; num3 = num1 ?? 5.34 ;
3 异常 try {} catch ( ExceptionName e){} catch (Exception ex){} finally {} Throw e
4 指针 static unsafe void Main () { int var = 20 ; int * p = &var; Console.WriteLine ("Data is: {0} " , p->ToString ()); } public static void Main () { unsafe { int var = 20 ; int * p = &var; Console.WriteLine ("Data is: {0} " , p->ToString ()); } }
三、结构 1 选择 if () {} else if () {} else {}switch (){ case 1 : break ;default :}
2 循环 for (i = 0 ;i < 5 ;i++)while (){}do {}while ();
3 方法
void
可接return;
返回
///
用于写方法注释
重载:同名不同参。
Random random = new Random(); int number = random.Next(1 ,101 );
四、数组 1 一维数组 int [] a;a = new int [n]; srting[] array = new string [2 ]{"a" ,"b" }; bool [] array = {true ,false }foreach (int i in array); Array arr1 = new ElemType[];
2 多维数组 int [,] array = new int [,];int [,] any = new int [5 ,3 ];int [,,,] array = new int [2 , 2 , 2 , 2 ];
3 交错数组
定义:不规则的表格(交错数组元素的单位是行(也就是数组))
int [][] array;array = new int [4 ][]; array[0 ] = new int [3 ];
4 参数数组
定义在方法参数中。
对方法内:数组。
对方法外:可以传入数组,可以传入一组同类型的数组,可以不传入参数。
5 数组方法 array.GetLength(n); array.Length;
五、存储 1 数据类型
分类:值类型,引用类型:
数组类型传入的是地址。(无需return)
bool值类型比较值,引用类型直接比引用。
array[0 ] = 2 ; arr = new int []{2 }; S1 = '男' ; ref int a;out int a;bool [type].TryParse(input, out result);
2 存储
CG:垃圾回收器(自动回收堆中的无引用数据。可手动,一般是交互时间最少的时候回收)
箱操作:
装箱:值->object(堆开辟空间,值存入堆中,返回堆地址)
拆箱:object->值(判断类型,返回已经装箱的引用)
非常消耗性能。(避免方法:重载,泛型)
字符串池:S1 =“ab”; S2="ab";
(S1与S2相等)
每次修改字符串相当于重新开辟了空间,object同理。
StringBuilder str = new StringBuilder(初始大小);
3 文件与IO操作 概念
System.IO:文件系统对应类。
DriveInfo:有关驱动器信息的类。
File:有关对文件整体操作及内容读写的类。
FileInfo:和File相似,不同之处是比FILE多了一个Length属性,通过该属性可以了解一个文件所占字节数。
Directory:有关文件夹的处理。
DirectoryInfo:功能同Directory,只是所有成员为实例成员。
Path:专用于对路径字符串的处理。
方法
File.Create(); File.Delete(); File.Move(); File.Copy(old,new ,bool ); File.Exists(); File.ReadAllText(path); File.ReadAllLines(path); File.ReadLines(); File.ReadAllBytes(); File.WriteAllText(path,string ); File.WriteAllLines(path,array); File.WriteAllBytes(); Directory.CreateDirectory(path); Directory.Delete(path,bool ); Directory.Move(); Directory.GetFiles(); Directory.GetDirectories(); Directory.Exists(path); Path.GetFileName(); Path.GetFileNameWithOutExtension(); Path.GetDirectoryName(); Path.Combine();
案例
private string path = @"D:/aa/bb" ;DirectoryInfo info = new DirectoryInfo(path); if (info.Exists) info.Create();using System;using System.IO;using System.Text;public class FileIO { public static string ReadFile (string filePath ) { try { using (FileStream fs = new FileStream(filePath, FileMode.Open)) { using (StreamReader reader = new StreamReader(fs, Encoding.UTF8)) { return reader.ReadToEnd(); } } } catch (Exception ex) { Console.WriteLine("An error occurred while reading the file: " + ex.Message); return null ; } } public static void WriteFile (string filePath, string content ) { try { using (FileStream fs = new FileStream(filePath, FileMode.Create)) { using (StreamWriter writer = new StreamWriter(fs, Encoding.UTF8)) { writer.Write(content); } } } catch (Exception ex) { Console.WriteLine("An error occurred while writing to the file: " + ex.Message); } } }
六、类与对象
my::简单线性表
my::二维数组方向
1 定义
一般情况:数据私有,方法公开。
类中方法外的变量:
具有默认值
存于堆。
可以与局部变量重名。(用this.区分)
类中的值:声明存在堆中,值也存于堆。
类中的引用:声明存在堆中,值也存在堆中,但是是存于另一个堆。
访问级别:
public :公有访问。不受任何限制,任何地方都可以引用,特殊场景不安全
private :私有访问。只限于本类成员访问,子类,实例都不能访问,可以用在本类种独有的方法。
protected :保护访问。只限于本类和子类访问,实例不能访问。
internal :内部访问。只限于本项目内访问,其他项目不能访问。
protected internal 组合:内部保护访问。只限于本项目或是子类访问,其他项目不能访问。
修饰符:
static:静态的(同类型类共用一个变量,通过类名调用)(类被加载时静态成员就存在)
static public class Name () {}
2 类中成员
构造函数:(访问级别)(类名)(){ }
new的时候使用的是构造函数。
一个类无构造函数会自动给一个无参构造函数。
构造函数:this( 本构造函数参数 ) 可以调用另一个构造函数。
构造函数级别:
public:公开类,创建对象时初始化。
private:无法在类外用这个类(称为单例)。
static:初始化类的静态数据成员,类被加载时调用一次。
public class Calculate { private int a; private int b; public int A { get { return a; } set { a = value ; } } public int B { get { return b; } set { b = value ; } } public int C { get ; set ; } public Calculate (int a ) { this .A = a; } public Calculate (int a, int b ) : this (a ) { this .B = b; } ~Calculate() { Console.WriteLine("End!" ); } public int add () { C = A + B; Console.WriteLine(C); return C; } public void Dispose () { GC.SuppressFinalize(this ); } }
3 使用 this .name;Wife wife01; wife01 = new Wife();
4 继承
子类可以用父类公共和保护类型代码,父类不能用子类代码。
父类私有代码子类不可以使用。
静态类不能被继承,但是静态方法和属性可以被继承。
一个子类只可以继承一个父类,但是可以继承多个接口。
class Animal { public void Eat () { Console.WriteLine("动物正在进食..." ); } } class Dog : Animal { public void Bark () { Console.WriteLine("狗在汪汪叫!" ); } } class Program { static void Main (string [] args ) { Dog dog = new Dog(); dog.Eat(); dog.Bark(); } }
5 引用
父类型的引用指向子类的对象,也就是说允许你使用基类(父类)的引用或变量来指向派生类(子类)的对象。
意思是说:假设有一个父类Person,有两个子类Student,Teacher。当我按Person person02 = new Student();
实例化时,person02
实际上只能访问父类中的内容,除非后续强制类型转化后才能访问对应子类的内容。
Person person02 = new Student(); Student stu02 = (Student)person02; Teacher teacher02 =(Teacher)person02; teacher02.Salary = 100 ; teacher people = student as teacher;
6 多态
静态多态性:编译时绑定方法关系。
动态多态性:运行时绑定方法关系。
public class Adds { public int Add (int a, int b ) { return a + b; } public int Add (int a, int b, int c ) { return a + b + c; } } public static Box operator + (Box a, Box b){ Box res = new Box(); res.length = a.length + b.length; return res.length; }
7 虚方法
重写虚方法就调用子类,不重写则调用父类。
protected virtual void Start (){ ...; } protected override void Start (){ base .Start(); ...; }
8 抽象类
C# 中的抽象类(abstract class)是一种不能直接实例化的类,它主要用于定义一个基类,并为派生类提供一个公共接口和部分实现。抽象类可以包含抽象方法(没有具体实现的方法,必须由派生类重写)、抽象属性以及普通成员(如字段、非抽象方法、静态成员等)。使用抽象类的主要目的是强制子类对某些成员进行实现。
抽象类特点:
用 abstract
关键字修饰的类是抽象类。
抽象类中可以有抽象方法(声明时使用 abstract
关键字且没有方法体)。
抽象类不能被实例化,只能作为其他类的基类来使用。
如果一个类包含至少一个抽象方法,则该类必须声明为抽象类。
派生自抽象类的非抽象子类必须实现所有抽象方法,否则子类也必须声明为抽象类。
public abstract class Animal { public abstract string Species { get ; set ; } public abstract void MakeSound () ; public Animal (string initialSpecies ) { Species = initialSpecies; } public void Sleep () { Console.WriteLine("Zzzz..." ); } } public class Dog : Animal { public override string Species => "Canine" ; public override void MakeSound () { Console.WriteLine("Woof!" ); } } Animal myDog = new Dog(); myDog.MakeSound();
9 using
使用using语句,用于自动释放实现了 IDisposable
接口的对象,以确保资源得到及时释放。
public int ExecuteNonQuery (string sql ){ using (sqlConnection conn= new sqlConnection(_connectionString)) { using (sqlCommand cmd = conn.CreateCommand()) { conn.Open(); cmd.CommandText = sql; return cmd.ExecuteNonQuery(); } } }
七、集合
内置的数据结构。
泛型和非泛型函数名是一样的。
using System.Collections;using System.Collections.Generic;
1 List ArrayList list = new ArrayList(); List<T> list = new List<T>(); List<int > numbers = new List<int >(); List<string > names = new List<string > { "Alice" , "Bob" , "Charlie" }; list.Count; list[0 ]; list.Last(); IndexOf(elem); list.Contains(elem); list.Add(elem); list.Insert(idx, elem); list.Remove(elem); list.RemoveAt(idx); list.Sort(); list.Reverse();
2 Dictionary
字典
Hashtable dict = new Hashtable(); Dictionary<key,value > dict = new Dictionary<key,value >(); Dictionary<key, value > dict = new Dictionary<key, value >(); dict.Keys; dict.Values; dict.Count value .GetInstanceID();dict.Add(key, value ); dict.Remove(key); dict.Clear(); dict.ContainsKey(key); dict.ContainsValue(value ); foreach (var pair in dict){ Console.WriteLine($"Key: {pair.Key} , Value: {pair.Value} " ); }
3 Stack
栈
Stack stack = new Stack(); Stack<T> stack = new Stack<T>(); stack.Push("str" ); stack.Pop(); stack.Peek(); stack.Count();
4 Queue
队列
Queue queue = new Queue(); Queue<T> queue = new Queue<T>(); queue.Enqueue("str" ); queue.Dequeue(); queue.Peek(); queue.Count();
八、高级 1 结构体
与类语法相似,但结构体属于值类型,类属于引用类型。
区别:结构体包含的无参数构造函数要给所有属性先赋值。
适用:点,颜色等轻量级对象。
using System;public struct Point{ public int x; public int y; public Point (int x, int y ) { this .x = x; this .y = y; } public void Print () { Console.WriteLine($"({x} , {y} )" ); } } public class Program { public static void Main () { Point p1 = new Point(1 , 2 ); p1.Print(); Point p2 = p1; p2.x = 3 ; p2.Print(); p1.Print(); } }
2 接口
接口中相当于填入方法的声明,继承接口的类要实现接口的所有方法。
接口默认公开,接口不能实例化。
接口可以继承接口。类只可以继承一个基类,但是可以继承多个接口。
接口常用于实现多态,代码框架等方面。
抽象类(Abstract Class):
状态携带 :抽象类可以包含字段(状态),即它可以有实例变量。这意味着抽象类可以保存状态,而不仅仅提供行为的抽象。
成员实现 :抽象类可以包含非抽象方法、构造函数、属性和事件,这意味着它可以提供一些默认的行为实现,而不仅仅是签名。
继承限制 :一个类只能继承一个抽象类,这是因为C#中的类继承是单继承的。这意味着如果你的类已经继承了一个基类,就不能再继承另一个抽象类。
构造函数 :抽象类可以有构造函数,这在创建具体类时可能会被调用。
访问修饰符 :抽象类可以有访问修饰符(如 public、protected、internal 等),这决定了它在哪些范围内可以被继承。
抽象成员 :抽象类中的抽象成员(方法、属性、索引器、事件)没有实现,它们必须在派生类中被覆盖(override)。
接口(Interface):
纯抽象 :接口只能包含抽象成员,不能有任何实现。这意味着接口中的所有成员(方法、属性、事件、索引器)都必须在实现该接口的类中显式地提供实现。
无状态 :接口不能包含字段或构造函数,因此它不能保存状态。接口关注的是行为,而非状态。
多重继承 :一个类可以实现多个接口,这弥补了C#中类的单继承限制,允许一个类拥有来自多个源的行为。
默认方法实现 (C# 8.0+):从C# 8.0开始,接口可以提供默认的方法实现,这使得接口更加灵活,可以在不破坏现有代码的情况下添加新成员。
访问修饰符 :接口本身没有访问修饰符,但是接口成员默认是公共的。
命名空间 :接口可以存在于任何命名空间中,这有助于组织和发现相关的接口。
选择建议:
当你需要定义一组相关行为,但不关心具体实现,并希望允许多重继承时,应使用接口。
当你需要定义一个基类,它可以包含部分实现、状态,以及你想限制继承的类数量时,应使用抽象类。
interface IMyInterface (){ void WriteLine () ; } class MyWriteSome : IMyInterface (){ public void WriteLine () { Console.WriteLine("Hello World!" ); } }
using System;public interface IAnimal { void MakeSound () ; } public abstract class Animal : IAnimal { public abstract void MakeSound () ; } public class Bird : Animal { public override void MakeSound () { Console.WriteLine("Bird is chirping." ); } } public class Dog : Animal { public override void MakeSound () { Console.WriteLine("Dog is barking." ); } } class Program { static void Main (string [] args ) { Bird bird = new Bird(); bird.MakeSound(); Dog dog = new Dog(); dog.MakeSound(); IAnimal animal1 = new Bird(); animal1.MakeSound(); IAnimal animal2 = new Dog(); animal2.MakeSound(); } }
3 命名空间
定义:命名空间是C#中用于组织代码和防止命名冲突的重要机制。它允许开发者将相关的类型(类、接口、枚举、委托等)分组到一个逻辑容器中,这有助于大型项目的管理和维护。
用途:
代码组织 :将相关的类型组织在一起,提高代码的可读性和可管理性。
避免命名冲突 :不同的命名空间可以使用相同的类型名,这在大型项目或使用多个外部库时尤为重要。
访问控制 :命名空间可以限制对特定类型或成员的访问,例如,使用 internal
访问修饰符可以使类型只在同一个解决方案内可访问。
声明命名空间:在C#中,命名空间使用关键字 namespace
来声明。命名空间的名称通常遵循反向域名的约定,例如 com.example.project
。
使用命名空间:在C#中,可以使用 using
指令在当前文件中导入其他命名空间中的类型,这样就可以直接使用类型名,而无需完整命名空间限定。
在C#中,命名空间可以嵌套,这意味着一个命名空间内部可以包含另一个命名空间。这在大型项目中非常有用,可以帮助进一步组织和分组代码。下面是一个示例,展示了嵌套命名空间的使用:
namespace com.example.mylib { public class MyClass { public void SayHello () { Console.WriteLine("Hello from MyClass!" ); } } } namespace com.example.client { using com.example.mylib; public class ClientClass { public void UseMyClass () { MyClass mc = new MyClass(); mc.SayHello(); } } }
namespace com.example.mylib { namespace sublib { public class SubClass { public void SayHello () { Console.WriteLine("Hello from SubClass!" ); } } } public class MyClass { public void SayHello () { Console.WriteLine("Hello from MyClass!" ); } } } namespace com.example.client { using com.example.mylib; using com.example.mylib.sublib; public class ClientClass { public void UseMyClass () { MyClass mc = new MyClass(); mc.SayHello(); SubClass sc = new SubClass(); sc.SayHello(); } } }
4 反射
定义:反射是.NET Framework中一项强大的特性,它允许程序在运行时检查和操作类型信息,包括类、方法、属性、事件等。反射可以用于动态创建对象、调用方法、读写字段或属性值,以及获取和操作元数据,如类型名称、命名空间、程序集信息等。这一特性在实现诸如动态配置、插件架构、元编程、框架和库开发、单元测试等方面非常有用。
程序集是.NET Framework中代码的物理单元,它包含了编译后的类型、资源和其他元数据。一个程序集可以是一个单独的DLL或EXE文件,也可以是一组多个文件组成的复合程序集。
Assembly
对象提供了关于程序集的详细信息,包括程序集的名称、版本、文化信息、公钥令牌、包含的类型和资源等。通过 Assembly
对象,你可以使用反射来动态地加载和访问程序集中的类型和成员。
namespace MyReflection { internal class MyClass { private int a; private int b; public int c; public string d; public string Name { get ; set ;} public string Sex { get ; set ; } public void FuncOne () {} public void FuncTwo () {} } } namespace MyReflection { internal class Program { static void Main (string [] args ) { Type t = typeof (MyClass); Console.WriteLine(t.Name); Console.WriteLine(t.Namespace); Console.WriteLine(t.Assembly); FieldInfo[] fis = t.GetFields(); foreach (FieldInfo fi in fis) { Console.WriteLine(fi.Name); } PropertyInfo[] pis = t.GetProperty(); foreach (FieldInfo pi in pis) { Console.WriteLine(pi.Name); } MethodInfo[] mis = t.GetMethod(); foreach (FieldInfo mi in mis) { Console.WriteLine(mi.Name); } } } }
*5 特性
定义:特性是一种允许我们向程序的程序集增加元数据的语言结构。它是用于保存程序结构信息的某种特殊类型的类。简单来说就是为某些数据额外增加一些信息。
using System;namespace MyAttribute { internal class Program { [Obsolete("这个方法弃用了,请使用NewTest方法" , false) ] static void Test () { Console.WriteLine("test" ); } static void NewTest () { Console.WriteLine("NewTest" ); } static void Main (string [] args ) { Test(); } } } #define IsShowMessage using System;using System.Diagnostics;namespace MyAttribute { internal class Program { [Conditional("IsShowMessage" ) ] static DebugShowMessage (string str ) { Console.WriteLine(str); } static void Main (string [] args ) { DebugShowMessage("Start of test" ); Console.WriteLine("Doing work in main" ); DebugShowMessage("End of test" ); } } }
public class HeroAttribute : Attribute { } public class
6 索引器
写在类中,类似于重载了类的索引。
索引器也可以进行重载,重载通过输入参数和返回值进行区分。使用时根据输入的参数不同来使用不同的索引器。
namespace IndexerApplication { class IndexedNames { private string [] namelist = new string [size]; static public int size = 10 ; public IndexedNames () { for (int i = 0 ; i < size; i++) namelist[i] = "N. A." ; } public string this [int index] { get { string tmp; if ( index >= 0 && index <= size-1 ) { tmp = namelist[index]; } else { tmp = "" ; } return ( tmp ); } set { if ( index >= 0 && index <= size-1 ) { namelist[index] = value ; } } } public int this [string name] {} static void Main (string [] args ) { IndexedNames names = new IndexedNames(); names[0 ] = "Zara" ; names[1 ] = "Riz" ; names[2 ] = "Nuha" ; names[3 ] = "Asif" ; names[4 ] = "Davinder" ; names[5 ] = "Sunil" ; names[6 ] = "Rubic" ; for ( int i = 0 ; i < IndexedNames.size; i++ ) { Console.WriteLine(names[i]); } Console.ReadKey(); } } }
7 委托
委托是存有对某个方法的引用的一种引用类型变量,用于实现事件和回调方法,所有的委托都派生自System.Delegate类。
委托相当于C++
的函数指针。
委托对象可以通过加减合并,形成调用列表。这称为委托的多播。内部数据结构是一个队列,先进先出。
namespace Test1 { class Test { delegate int NumberChanger (int n ) ; static int num = 10 ; public static int AddNum (int p ) { num += p; return num; } public static int MultNum (int q ) { num *= q; return num; } public static int getNum () { return num; } static void Main (string [] args ) { NumberChanger nc = new NumberChanger(AddNum); nc(25 ); Console.WriteLine("Value of Num: {0}" , getNum()); nc = MultNum; nc(5 ); Console.WriteLine("Value of Num: {0}" , getNum()); } } } static void Main (string [] args ){ NumberChanger nc; NumberChanger nc1 = new NumberChanger(AddNum); NumberChanger nc2 = new NumberChanger(MultNum); nc = nc1; nc += nc2; nc(5 ); Console.WriteLine("Value of Num: {0}" , getNum()); }
Action sayHello = () => Console.WriteLine("Hello!" ); sayHello(); Action<string > sayHelloTo = (name) => Console.WriteLine("Hello, " + name + "!" ); sayHelloTo("John" ); Func<int , int , int > add = (a, b) => a + b; int result = add (3 , 5 );Console.WriteLine(result);
8 事件
发布器(publisher) 是一个包含事件和委托定义的对象。事件和委托之间的联系也定义在这个对象中。发布器(publisher)类的对象调用这个事件,并通知其他的对象。
订阅器(subscriber) 是一个接受事件并提供事件处理程序的对象。在发布器(publisher)类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。
public class Demo { private int myValue; public int MyValue { get { return myValue; } set { myValue = value ; MyValueChanged?.Invoke(); } } public event Action MyValueChanged; public void OnMyValueChanged () { Console.WriteLine("Changed!" ); } } public class Program { public static void Main (string [] args ) { Demo demo = new Demo(); demo.MyValueChanged += demo.OnMyValueChanged; demo.MyValue = 10 ; demo.MyValue = 10 ; demo.MyValue = 10 ; } } public class MyClass { public event EventHandler MyEvent; public void OnMyEvent () { MyEvent?.Invoke(this , EventArgs.Empty); } } public class Program { public static void Main (string [] args ) { MyClass myObject = new MyClass(); myObject.MyEvent += MyEventHandler; myObject.OnMyEvent(); } private static void MyEventHandler (object sender, EventArgs e ) { Console.WriteLine("Event handled!" ); } }
9 泛型
泛用类型,T可以是不同的数据类型。
约束类型
作用
where T: struct
T必须是一个值类型
where T : class
T必须是一个引用类型
where T : new()
T必须有一个无参数的公共构造函数
where T : <base class name>
T必须是指定的基类或派生自指定的基类
where T : <interface name>
T必须实现指定的接口
where T : U
T必须是U或派生自U
where T : notnull
T不能为null
where T : unmanaged
T必须是非托管类型
static void Swap <T >(ref T lhs, ref T rhs ){ T temp; temp = lhs; lhs = rhs; rhs = temp; } public class GenericClass <T1 , T2 >{ private T1 genericMember1; private T2 genericMember2; public GenericClass (T1 value1, T2 value2 ) { genericMember1 = value1; genericMember2 = value2; } } delegate T NumberChanger <T >(T n ) ;public void Request <T >() where T : class
10 匿名方法
没有名字的方法。例如:lambda表达式。
using System;class Program { delegate int ArithmeticOperation (int x, int y ) ; static void Main () { ArithmeticOperation addition = delegate (int x, int y) { return x + y; }; ArithmeticOperation multiplication = delegate (int x, int y) { return x * y; }; int resultAdd = addition(3 , 5 ); int resultMultiply = multiplication(3 , 5 ); Console.WriteLine($"Addition result: {resultAdd} " ); Console.WriteLine($"Multiplication result: {resultMultiply} " ); } } using System;class Program { delegate int ArithmeticOperation (int x, int y ) ; static void Main () { int a = 5 ; Func<int , int > f = x => x + a; Console.WriteLine(f(4 )); a = 8 ; Console.WriteLine(f(4 )); } }
*11 多线程