CSharpStudy


微软官方文档


基础知识


类型

值类型

名称 含义 范围 .Net框架类型 默认值
sbyte 8位有符号整数 -128~127 System.Sbyte 0
byte 8位无符号整数 0~255 System.byte 0
short 16位有符号整数 -32768~32767 System.Int16 0
ushort 16位无符号整数 0~35535 System.UInt16 0
int 32位有符号整数 -2147 483 648~

2 147 483 647
System.Int32 0
uint 32位无符号整数 0~4 294 967 295 System.UInt32 0
long 64位有符号整数 -9 223 372 036 854 775 808~

9 223 372 036 854 775 807
System.Int64 0
ulong 64位无符号整数 0~18 446 744 073 709 551 615 System.UInt64 0
float 单精度浮点数 1.510 -45~

3.4
10 38
System.Single 0.0f
double 双精度浮点数 510 -324~

1.7
10 308
System.Double 0.0d
bool 布尔型 true 或 false System.Boolean false
char Unicode字符串 U+0000~U+ffff System.Char '\0' 即 null
decimal 小数类型的有效数字精度为28位 +-1.010 28~

+-7.9
10 28
System.Decimal 0m

方法

#未完成

ref引用

int i = 10; 
ref int j = ref i; //j = 20; //i 也会变为 20 
ChangeValue(ref i);// 必须加 ref ,不然报错 
void ChangeValue(ref int value) 
{ 
	value = 20; 
} 
Console.WriteLine(i);// 20

字符串

字符串内插(C#6.0-2015年7月)

int a = 16; 
string s = "Hello, World!";
string s2 = $"{s}, Goodbye, World!, {a}"; Console.WriteLine(s2); 
string s3 = @"C:\users";// 引号前面加@(称作"逐字字符串")将转义字符(\)当作普通字符对待

原始字符串(C#11-2022年11月发布)

string oStr = """ 
	Hello World 
		This is a multi-line string 
	""";
Console.WriteLine(oStr);
string str = "Ace"; 
int age = 16; 
string oStr = $""" 
{ 
	"name":"{{str}}", 
	"age":{{age}} 
} 
"""; 
Console.WriteLine(oStr);

结构体

#未完成


枚举

#未完成


数组

#未完成


集合

ArrayList

using System.Collections; 

ArrayList arrayList = new ArrayList(); 
arrayList.Add(10); 
arrayList.Add("Hello"); 
arrayList.Add(true); 
arrayList.Insert(1, "World"); 
arrayList.Remove(10); 
arrayList.RemoveAt(1); 
arrayList.Clear(); 

foreach (var item in arrayList) 
{ 
	Console.WriteLine(item); 
}

List<>

List<string> names = new List<string>() { "John", "Mary", "Peter" }; 
names.Add("Tom"); 
names.Add("Jane"); 
names.Insert(1, "Lily");
names.Remove("Mary"); 
names.AddRange(new string[]{"zhang", "wang", "li", "zhao"}); names.AddRange(names); 

foreach (var name in names) 
{
	Console.WriteLine(name); 
}
// List泛型集合可以转换为数组,同样数组可以转换成泛型集合 
string[] names2 = names.ToArray();
List<string> list = name2.ToList(); 

names.Clear(); 
Console.WriteLine(names.Count);
int[] xs = new int[] { 4, 7, 9 }; 
var limits = FindMinMax(xs); 
Console.WriteLine($"Limits of [{string.Join(" ", xs)}] are {limits.min} and {limits.max}"); 
// Output: 
// Limits of [4 7 9] are 4 and 9 

int[] ys = new int[] { -9, 0, 67, 100 }; 
var (minimum, maximum) = FindMinMax(ys); Console.WriteLine($"Limits of [{string.Join(" ", ys)}] are {minimum} and {maximum}"); 
// Output:
// Limits of [-9 0 67 100] are -9 and 100 

(int min, int max) FindMinMax(int[] input) 
{ 
	if (input is null || input.Length == 0) 
	{ 
		throw new ArgumentException("Cannot find minimum and maximum of a null or empty array."); 
	} 
	
	// Initialize min to MaxValue so every value in the input 
	// is less than this initial value. 
	var min = int.MaxValue; 
	// Initialize max to MinValue so every value in the input 
	// is greater than this initial value. 
	var max = int.MinValue;
	 foreach (var i in input) 
	 { 
		 if (i < min) 
		 { 
			 min = i; 
		 } 
		 if (i > max) 
		 { 
			 max = i; 
		 } 
	 } 
	 return (min, max); 
}

字典

字典

using System.Collections.Generic; 

Dictionary<string, int> studentScores = new Dictionary<string, int>(); 

studentScores.Add("张三", 85); 
studentScores.Add("李四", 90); 
studentScores.Add("王五", 95);
studentScores["赵六"] = 75; 
studentScores.Remove("王五"); 
studentScores.Remove("aa");// 如果要删除的键值对在字典中不存在,也不会报错 

if (studentScores.ContainsKey("张三")) 
{
	Console.WriteLine(studentScores["张三"]);
} 

Dictionary<string, int> scores = new Dictionary<string, int>() 
{ 
	{"张三", 85}, 
	{"王五", 95}, 
	{"赵六", 75}, 
}; 
Dictionary<string, int> scores2 = new() { {"张三", 85}, {"王五", 95}, {"赵六", 75}, }; foreach (var item in studentScores) { Console.WriteLine($"{item.Key}: {item.Value}"); }

只读字典

Dictionary<string, float> dict = new Dictionary<string, float>(); 
dict.Add("张三", 85.5f); 
dict.Add("王五", 95.5f); 
dict.Add("赵六", 75.5f); 

var b = dict.AsReadOnly();

foreach (var item in b) 
{ 
	Console.WriteLine(item.Key + " " + item.Value); 
} 

var readOnlyDict = new ReadOnlyDictionary<string, float>(dict); 
//readOnlyDict["张三"] = 90.5f;// 报错,只读 

Console.WriteLine(readOnlyDict["张三"]);

foreach (var item in readOnlyDict) 
{ 
	Console.WriteLine(item.Key + " " + item.Value); 
}

面向对象

Student stu1 = new Student { Name = "John", Age = 16 }; Student stu2 = new() { Name = "Mary", Age = 17 }; Console.WriteLine(stu1.Name + stu1.Age); Console.WriteLine(stu2.Name + stu2.Age); 

class Student 
{ 
	public string Name { get; set; } 
	public int Age { get; set; } 
}

类继承

class Vehicle 
{ 
	public Vehicle(string vOwner) 
	{ 
		this.Owner = vOwner;
	} 
	
	public string Owner { get; set; } 
	
} 

class Car : Vehicle 
{ 
	// 因为父类只有有参构造,所以子类要 
	public Car(string cOwner) : base(cOwner)//先赋值给 Car 的cOwner ,后 base 的 
	{ 
		//this.Owner = cOwner 
	} 
	// 或者 
	public Car() : base("N/A") 
	{ 
		this.Owner = "Car Owner"; 
	} 
	public void ShowOwner()
	{
		Console.WriteLine(Owner); 
	} 
}
class Vehicle 
{ 
	public string Owner { get; set; } 
	
	protected void ShowOwner() 
	{ 
		Console.WriteLine(Owner); 
	} 
} 
public static void Main()
{ 
	Vehicle vehicle = new Vehicle("John");
	vehicle.ShowOwner();// 不行,报错:不可访问, 
	//因为它具有一定的保护级别 
}

密封类

public sealed Class Student:Person {}

重写

class Vehicle 
{ 
	public void Run() 
	{
		Console.WriteLine("Vehicle is running"); 
	} 
} 
class Car : Vehicle 
{ 
	public void Run() 
	{
		Console.WriteLine("Car is running"); 
	} 
}
class Vehicle 
{ 
	public virtual void Run() 
	{ 
		Console.WriteLine("Vehicle is running"); 
	} 
} 
class Car : Vehicle 
{ 
	public override void Run() 
	{ 
		Console.WriteLine("Car is running"); 
	} 
}
Vehicle vehicle = new Car();
vehicle.Run();

抽象类

依赖反转


接口


用什么方式实现多态

什么时候用虚方法来实现多态?
什么时候用抽象类来实现多态?
什么时候用接口来实现多态?

委托

声明委托类型

delegate void MyDel(int x);

创建委托对象

创建委托对象

注意

若使用 new 运算符创建,圆括号里必须写一个方法,不能不写也不能写两个及以上

delegate void MyDelegate(string message); 

// 方法一:使用带 new 运算符的对象创建表达式 
MyDelegate delVar = new MyDelegate(myInstObj.Mym1);// 创建委托并保存引用 

// 方法二:使用快捷语法
MyDelegate delVar = myInstObj.Mym1;// 创建委托并保存引用

委托的一般使用

注意

应该适时地使用接口取代一些对委托的使用

  • Java完全地使用接口取代了委托的功能,即Java没有与C#中委托相对应的功能实体

多播委托

增加方法

Mydel delVar = M1;// 创建委托并初始化 
delVar += M2;//增加方法 
delVar += M3;//增加方法 

/*由于委托是不可变的,所以为委托的调用列表添加三个方法后的结果 其实是变量指向一个全新的委托*/

移除方法

delVar -= SCL.m3// 从委托移除方法

调用委托

Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object. at Program.<Main>$(String[] args) in E:\Computer\VS\Console\ConsoleApp1\ConsoleApp1\Program.cs:line 273
为避免调用空委托,可以使用空条件运算符
MyDel delVar = inst.Mym1; 
delVar += scl.m3; 
delVar += x.act; 

if(null != delVar)// 确认委托有方法 
{ 
	delVar(53); // 调用委托 
} 
else 
{ 
	Console.WriteLine("委托是空的") 
} 
/* 
在调用委托时,它使用相同的参数来调用调用列表中的每一个方法 inst.mym1(53); scl.m3(53); x.act(53); 
*/

调用带返回值的委托

调用带引用参数的委托

匿名方法(C#2.0 2005-11-07)

语法

delegate(参数列表){语句块}
// 使用具名方法 
class Program 
{ 
	public static int Add20(int x) 
	{ 
		return x + 20 ; 
	} 
	delegate int OtherDel(int a); 
	static void Main() 
	{ 
		OtherDel del = Add20;
		Console.WriteLine("{0}", del(5)); 
	} 
} 

// 使用匿名方法 
class Program 
{ 
	delegate int OtherDel(int a); 
	static void Main() 
	{ 
		OtherDel del = delegate(int x) 
		{ 
			return x + 20;
		}; 
		Console.WriteLine("{0}", del(5)); 
	} 
}

返回类型

delegate int Del(int param); 

static void Main() 
{ 
	Del del = delegate(int x) 
	{ 
		return x + 20; // 返回一个整型值 
	}; 
}

params 参数

// 在委托类型声明中使用 params 关键字 
delegate void Somedel(ibt x, params int[] y); 
// 在匹配的匿名方法中省略关键字 
Somedel mDel = delegate(int x, int[] y) 
{ 
	... 
};

Lambda 表达式(C#3.0 2007-11-06)

delegate double Mydel(int par); 

Mydel del = delegate(int x){return x + 1;}; // 匿名方法 
Mydel lam1 =        (int x) => {return x + 1;}; // Lambda 表达式 
Mydel lam2 =            (x) => {return x + 1;}; // Lambda 表达式 
Mydel lam1 =             x => {return x + 1;}; // Lambda 表达式 
Mydel lam1 =             x => x + 1; // Lambda 表达式

事件

简介

  1. 事件的误传: 认为事件是一种特殊的委托类型字段

    • 类中有字段了,但还是有属性这个东西,事件和委托差不多也是这个关系[1]
  2. 事件最大的特点就是能够发生。如果一个作为主语的名词,可以使用“发生”这个词来做它的谓语动词的话,那么它就是一个事件。例如:

    • 苹果,我们不能说一个苹果发生了
    • 公司上市、产品发布,它们是可以发生的, 所以这俩是事件
  3. 事件是一种类型的成员

    • 凡是事件,都是隶属于某一个主体的,没有公司,就不会有“上市”这个事件发生;没有产品,就不会有”发布“这个事件发生
  4. 事件的功能

    • 事件是使对象或类具备通知能力的成员
    • 事件的功能 = 通知 + 可选的事件参数(即详细信息)
  5. 事件的使用

    • 用于对象或类间的动作协调与信息传递(消息推送)
  6. 事件原理:事件模型中的两个“5”

    • "发生→响应"中的5个部分——闹钟响了你起床、孩子饿了你做饭....这里隐含着"订阅"关系
    • "发生→响应"中的5个动作——
      • (1)我有一个事件→
      • (2)一个人或者一群人关心我的这个事件→
      • (3)我的这个事件发生了→
      • (4)关心这个事件的人会被依次通知到→
      • (5)被通知到的人根据拿到的事件信息(又称"事件数据"、"事件参数"、"通知")采取行动,称为对事件进行响应(又称"处理事件")。
  7. 约定的术语

    • 这四个是一个意思
      • 事件的订阅者
      • 事件消息的接收者
      • 事件的响应者
      • 被事件所通知的对象
    • 事件的处理者
    • 这四个是一个意思
      • 事件信息
      • 事件消息
      • 事件数据
      • 事件参数

事件的应用

// 事件的拥有者
class Program
{
	static void Main(string[] args)
	{
		System.Timers.Timer timer = new System.Timers.Timer();
		timer.Interval = 1000;
		Boy boy = new Boy();
		timer.Elapsed += boy.Action;
		Girl girl = new girl();
		timer.Elapsed += girl.Action;
		timer.Start();
		Console.ReadKey();
	}
}

// 事件的响应者
class Boy
{
	// 事件处理器
    internal void Action(object? sender, ElapsedEventArgs e)
    {
        Console.WriteLine("Jump!");
    }
}
class Girl
{
	// 事件处理器
    internal void Action(object? sender, ElapsedEventArgs e)
    {
        Console.WriteLine("Sing!");
    }
}
---

config:

  look: neo

  theme: default

---

flowchart RL

 subgraph s1["事件的拥有者"]

        n1["事件"]

  end

 subgraph s2["事件的响应者"]

        n2["事件处理器"]

  end

    n2 -- 订阅 --> n1
class Program
{
	static void Main(string[] args)
	{
		// 事件的拥有者为 Form
		Form form = new Form();
		Controller controller = new Controller(form);
		form.ShowDialog();
	}
}
// 事件的响应者为 Controller
class Controller
{
	private Form _form;
	public Controller(Form form)
	{
		if(form != null)
		{
			_form = form;
			// 订阅
			_form.Click += this.FormClicked;
		}
	}
	// 事件处理器
	private void FormClicked(object sender, EventArgs e)
	{
		_form.text = DataTime.New.ToString();
	}
}
---

config:

  look: neo

  theme: default

---

flowchart

 subgraph s2["事件的拥有者同时也是事件的响应者"]

        n2["事件处理器"]

        n3["事件"]

  end

    n2 -- 订阅 --> n3
class Program
{
	static void Main(string[] args)
	{
		// 事件的拥有者为 MyForm
		MyForm myForm = new MyForm();
		myForm.Click += myForm.FormClicked;
		myForm.ShowDialog();
	}
}
class MyForm:Form
{
	// 事件的响应者还是事件拥有者它自己
	// 事件处理器
	void FormClicked(object sender, EventArgs e)
	{
		this.Text = DataTime.Now.ToString();
	}
}

flowchart TB

 subgraph s2["事件的拥有者"]

        n2["事件"]

  end

 subgraph s1["事件的响应者"]

        n1["事件处理器"]

        s2

  end

    n1 -- 订阅 --> n2
class Program
{
	static void Main(string[] args)
	{
		// 事件的响应者为 MyForm
		MyForm myForm = new MyForm();
		myForm.ShowDialog();
	}
}
// 窗口有按钮和文本框成员,按钮是事件拥有者,窗口是事件响应者
class MyForm:Form
{
	private TextBox textBox;
	// 事件的拥有者为 Button
	private Button button;
	
	public MyForm()
	{
		this.textBox = new TextBox();
		this.button = new Button();
		this.Controls.Add(this.texbox);
		this.Controls.Add(this.button);
		this.button.Click += this.ButtonCLicked;
		this.button.Text = "SayHello";
		this.button.Top = 100;// 按钮的上边界距窗口距离
	}
	// 事件处理器
	private void ButtonClicked(object sender, EventArgs e)
	{
		this.textBox.Text = "Hello World";
	}
}

一个事件可以同时挂接多个事件处理器
Boy、Girl 的例子

一个事件处理器可以被多个事件挂接

#未完成

事件的自定义声明

完整声明

delegate void CallWaiterEventHandler(Customer customer);

class Customer
{
	// 声明委托类型字段,用来存储引用事件处理器
	private CallWaiterEventHandler _callWaiter;
	// 顾客叫服务员事件
	public event CallWaiterEventHandler CallWaiterEvent
	{
	    add
	    {
	        _callWaiter += value;
	    }
	    remove
	    {
	        _callWaiter -= value;
	    }
	}
}

简略声明

// 顾客点餐事件
public event EventHandler<OrderEventArgs> Order;

例子

graph LR
	顾客进饭馆-->喊服务员点餐-->服务员展示菜单-->顾客点餐-->服务员上菜-->顾客结账-->服务员展示账单-->顾客付款

事件与委托的关系

为什么要使用委托类型来声明事件?


转换

显式转换

装箱、拆箱


IO文件

Path类-路径操作

string str = @"C:\3000soft\RedSPider\Data\Message\老赵.wav"; // 获得文件名 
Console.WriteLine(Path.GetFileName(str));// 老赵.wav
// 获得文件名但是不包含扩展名 
Console.WriteLine(Path.GetFileNameWithoutExtension(str));// 老赵
// 获得文件的扩展名 
Console.WriteLine(Path.GetExtension(str));// .wav 
// 获得文件所在的文件夹的名称 
Console.WriteLine(Path.GetDirectoryName(str));// C:\3000soft\RedSPider\Data\Message 
// 获得文件所在的全路径 
Console.WriteLine(Path.GetFullPath(str));// C:\3000soft\RedSPider\Data\Message\老赵.wav 
// 连接路径
Console.WriteLine(Path.Combine(@"c:\a\", "b.txt"));// c:\a\b. txt

File类-文件操作

// 创建文件 
// 再次运行创建,只会修改第一次创建的把它的内容清空,可以看下文件属性的创建时间、修改时间 
string str = @"C:\Users\Zhang\Desktop\test"; File.Create(str+@"\test.txt");
// 删除文件,不放入回收站直接删除 
File.Delete(str + @"\test.txt"); 
// 复制文件 
File.Copy(str + @"\test.txt", str + @"\test2.txt");

读取文件

// 方法一:ReadAllBytes 
string str = @"C:\Users\Zhang\Desktop\钱塘湖春行.txt"; byte[] bytes = File.ReadAllBytes(str); 
string content = Encoding.UTF8.GetString(bytes); Console.WriteLine(content); 

// 方法二:ReadAllLines 
string strAddress = @"C:\Users\Zhang\Desktop\钱塘湖春行.txt"; 
// ReadAllLines方法会返回指定路径文件的所有行内容,并以字符串数组的形式返回。 
string[] contents = File.ReadAllLines(strAddress); foreach (string content in contents) 
{ 
	Console.WriteLine(content); 
} 

// 方法三:ReadAllText 
string contents = File.ReadAllText(strAddress); Console.WriteLine(contents);

写入文件

// 方法一:WriteAllBytes 
string strAddress = @"C:\Users\Zhang\Desktop\阿大.txt"; 
string str = "今天天气好晴朗,处处好风光。";
string str2 = "你好,世界!"; 
// 将字符串转换成字节数组 
byte[] bytes = Encoding.UTF8.GetBytes(str2); 
// 将字节数组写入文件,如果没有这个文件,则创建这个文件,有的话则覆盖原文件 
File.WriteAllBytes(strAddress, bytes); 

// 方法二:WriteAllLines 
string strAddress = @"C:\Users\Zhang\Desktop\阿大.txt"; 
string[] str = { "今天天气好晴朗,处处好风光。", "你好,世界!" , "张三李四王五赵六。"}; 
File.WriteAllLines(strAddress, str); 

// 方法三:WriteAllText 
string str = "今天天气好晴朗,处处好风光。" + "你好,世界!" + "张三李四王五赵六。"; 
File.WriteAllText(strAddress, str);
往文件追加内容,而不是覆盖
string str = "打开一个文件,向其中追加指定的字符串,然后关闭该文件。如果文件不存在,此方法创建一个文件,将指定的字符串写入文件,然后关闭该文件。"; 
// 打开一个文件,向其中追加指定的字符串,然后关闭该文件。如果文件不存在,此方法创建一个文件,将指定的字符串写入文件,然后关闭该文件。 
File.AppendAllText(strAddress, str);

FileStream

读取文件

string strAddress = @"C:\Users\Zhang\Desktop\阿大.txt"; 
FileStream fs = new FileStream(strAddress, 
FileMode.Open, FileAccess.Read); 
byte[] buffer = new byte[1024*1024*5];// 每次读取5M 
int r = fs.Read(buffer, 0, buffer.Length);// 返回本次实际读取到的有效字节数 
string content = Encoding.UTF8.GetString(buffer); 
// 关闭文件流 
fs.Close(); 
// 释放流所占用的资源 
fs.Dispose(); 
Console.WriteLine(content);

写入文件

string strAddress = @"C:\Users\Zhang\Desktop\阿大.txt";
using (FileStream fw = new FileStream(strAddress, 
FileMode.Open, FileAccess.Write))
{ 
	string str = """ 
			钱塘湖春行 
			唐代:白居易 
	孤山寺北贾亭西,水面初平云脚低。 
	几处早莺争暖树,谁家新燕啄春泥。 
	乱花渐欲迷人眼,浅草才能没马蹄。 
	最爱湖东行不足,绿杨阴里白沙堤。 
	"""; 
	byte[] buffer = Encoding.UTF8.GetBytes(str); 
	fw.Write(buffer, 0, buffer.Length);
}

StreamReader、StreamWriter

string strAddress = @"C:\Users\Zhang\Desktop\阿大.txt"; 
using(StreamReader sr = new StreamReader(strAddress, Encoding.UTF8)) 
{ 
	while(!sr.EndOfStream) 
	{ 
		Console.WriteLine(sr.ReadLine());
	} 
} 

using (StreamWriter sw = new StreamWriter(strAddress, true, Encoding.UTF8)) 
{
	sw.WriteLine("看我有木有把你覆盖掉"); 
}

加密

string str = "123"; 
string md5 = GetMD5(str);
// result: 202cb962ac59075b964b07152d234b70 
// strNew: 202CB962AC59075B964B07152D234B70 
Console.WriteLine(md5); 

static string GetMD5(string str) 
{ 
	// 创建 MD5 对象 
	MD5 md5 = MD5.Create(); 
	// 开始加密 
	// 需要将字符串转换成字节数组 
	byte[] buffer = Encoding.UTF8.GetBytes(str); 
	// 返回一个加密好的字节数组 
	byte[] newBuffer = md5.ComputeHash(buffer); 
	// 将加密好的字节数组转换成字符串 
	string result = BitConverter.ToString(newBuffer).Replace("-", "").ToLower(); 
	
	// 将字节数组中的每一个元素ToString 
	string strNew = ""; 
	for (int i = 0; i < newBuffer.Length; i++) 
	{ 
	strNew += newBuffer[i].ToString("X2");
	// 如果用小写x2,就是小写的字母 
	} 
	return strNew; 
}

?、??、?. 运算符

(?)可空类型修饰符(C#2.0-2005-11-07)

(??) 空合并运算符(C#8.0-2019-04-18)

string a = null;
a = "Hello" ?? "World"; 
Console.WriteLine(a);// Hello 

a = null ?? "world"; 
Console.WriteLine(a);// world

(??=)空合并赋值运算符 (C#8.0-2019-04-18)

string nickname = null;// 昵称 
//nickname = nickname ?? "CoolCoder"; 
nickname ??= "CoolCoder"; 
Console.WriteLine(nickname); // 输出: CoolCoder 

string username = "DeveloperDave"; 
//username = username ?? "Newbie"; 
username ??= "Newbie"; 
Console.WriteLine(username); // 输出: DeveloperDave(未改变,因为原本不为null)

(?.)空条件运算符 (C#8.0-2019-04-18)

Person person = null;
string jobTitle = person?.JobTitle; Console.WriteLine(jobTitle); // 输出: null(而不是引发异常) 

person = new Person { JobTitle = "Software Engineer" }; jobTitle = person?.JobTitle; 
Console.WriteLine(jobTitle); // 输出: Software Engineer

杂项

命名约定

风格名称 描述 推荐使用 示例
Pascal大小写 标识符中每个单词的首字母大写 用于:命名空间、类、结构、接口、委托、属性、事件、和公共字段、公共方法 CardDeck、Dealershand
Camel大小写 标识符中第一个单词首字母小写,其他单词首字母大写 用于局部变量的名称和方法声明的形参名称 totalCycleCount、randomSeedParm
下划线加Camel小写 以下划线开头的Camel大小写 private、internal;static 的 private或interenal 用s_;线程静态用t_ _cycleCount、_selectedIndex

怎么写注释

/// <summary> 
/// 在这里简单描述类、方法主要是干什么的。<br/> 
/// 像 <see langword="bool"/> 这样写,可以给关键字啥的添加颜色<br/> 
/// <see cref="MyIntProperty" />, 添加超链接<br/> 
/// </summary> 
/// <remarks> 
/// <para> 
/// 这里可以详细写原理、算法、设计思想等。 
/// </para> 
/// </remarks> 
/// <example> 
/// <code> 
/// 在这里写示例代码 
/// MyClass myClass = new MyClass();
/// myClass.MyMethod(); 
/// </code> 
/// </example> 
/// <param name="a">在这里写参数a的描述</param> 
/// <param name="b">在这里写参数b的描述</param> 
/// <returns>在这里写返回值描述</returns>

获取变量类型

Type t = typeof(Zhangsan); 
Type tb = t.BaseType; 
Zhangsan zs = new Zhangsan(); 

Console.WriteLine(t);// Zhangsan 
Console.WriteLine(tb);// Person 
Console.WriteLine(zs.GetType().Name)// Zhangsan 

// 没有写继承哪个类默认继承自 Object 类 
class Person 
{ 
	public string Name { get; set; } 
	public int Age { get; set; } 
} 

class Zhangsan : Person 
{ 
	public string Address { get; set; } 
}

测试程序运行时间

using System.Diagnostics; 

Stopwatch sw = new Stopwatch();
sw.Start(); 

foreach (var item in arrayList) 
{ 
	Console.WriteLine(item);
} 
sw.Stop();
Console.WriteLine($"Time elapsed: {sw.Elapsed}");

控制台

不会重复的Guid

Guid guid = Guid.NewGuid(); 
Console.WriteLine(guid);

遍历数组

int[] arr = { 1, 2, 3, 4, 5 }; 
//foreach (var item in arr) 
//{ 
	// Console.Write(item + " ");
//} 

// 对指定数组的每个元素执行指定操作。 
Console.WriteLine("开始:"); 
Array.ForEach<int>(arr, x => Console.Write(x + " ")); 

Array.ForEach<int>(arr, x => x *= 2); 
Console.WriteLine("\nArray.ForEach +=2后:"); 

Array.ForEach<int>(arr, x => Console.Write(x + " ")); 

arr = arr.Select(x => x * 2).ToArray(); 
Console.WriteLine("\nselect *=5后:"); 

Array.ForEach<int>(arr, x => Console.Write(x + " ")); 
/* 
开始: 
1 2 3 4 5 
Array.ForEach *=2后:
1 2 3 4 5 
select *=5后: 
2 4 6 8 10 
*/

CSharp反汇编


进阶知识

泛型

#未完成

泛型类

class SomeClass <T1, T2>
{
	T1 SomeVar = new T1();
	T2 OtherVar = new T2();
}
SomeClass<short, int> mySc1 = new SomeClass<short, int>;

Linq

#未完成


多线程、异步编程

简介

异步调用

Student stu1 = new Student { Name = "张三", PenColor = ConsoleColor.Green };
Student stu2 = new Student { Name = "李四", PenColor = ConsoleColor.Yellow };
Student stu3 = new Student { Name = "王五", PenColor = ConsoleColor.Blue };

Action action = stu1.DoHomework;
action += stu2.DoHomework;
action += stu3.DoHomework;

class Student
{
    public string Name { get; set; }
    public ConsoleColor PenColor { get; set; }

    public void DoHomework()
    {
        for (int i = 0; i < 5; i++)
        {
            Console.ForegroundColor = PenColor;
            Console.WriteLine($"{Name} doing homework {i + 1} hours");
            Thread.Sleep(1000);// 暂停1秒
        }
    }
}

隐式异步调用

// .net core平台不支持多线程调用,要换成.net framework
action.BeginInvoke(null, null);// 隐式异步调用

显式异步调用

// Thread 显式异步调用
Thread thread1 = new Thread(new ThreadStart(stu1.DoHomework));
Thread thread2 = new Thread(new ThreadStart(stu2.DoHomework));
Thread thread3 = new Thread(new ThreadStart(stu3.DoHomework));

thread1.Start();
thread2.Start();
thread3.Start();

/*
 结果:
张三 doing homework 1 hours
李四 doing homework 1 hours
王五 doing homework 1 hours
李四 doing homework 2 hours
王五 doing homework 2 hours
张三 doing homework 2 hours
张三 doing homework 3 hours
李四 doing homework 3 hours
王五 doing homework 3 hours
王五 doing homework 4 hours
张三 doing homework 4 hours
李四 doing homework 4 hours
王五 doing homework 5 hours
李四 doing homework 5 hours
张三 doing homework 5 hours
 
 */

// Task 显式异步调用
Task task1 = new Task(new Action(stu1.DoHomework));
Task task2 = new Task(new Action(stu2.DoHomework));
Task task3 = new Task(new Action(stu3.DoHomework));

task1.Start();
task2.Start();
task3.Start();
Task.WaitAll(task1, task2, task3);

---

Task task1 = Task.Run(() => stu1.DoHomework());
Task task2 = Task.Run(() => stu2.DoHomework());
Task task3 = Task.Run(() => stu3.DoHomework());

Task.WaitAll(task1, task2, task3);

反射和特性

#未完成


solid设计原则

S-single responsibility principle(SRP)—单一职责原则

O—open closed principle(OCP)——开闭原则

L—liskov substitution principle(LSP)—里氏替换原则

I—interface segregation principle(ISP)—接口隔离原则

D—depend inversion principle(DIP)—依赖倒置原则


始建于:2025-3-15-17:24



  1. 引用于:刘铁猛《C#语言入门详解》全集 1分25秒处弹幕 ↩︎

  2. 引用于:刘铁猛《C#语言入门详解》全集 1:02:06 处弹幕 ↩︎