异步编程
关于线程默认情况下一个进程只包含一个线程。线程可以派生其他线程,因此在任意时刻,一个进程可能包含不同状态的多个线程,它们执行程序的不同部分。如果一个进程拥有多个线程,它们将共享进程的资源。系统为处理器执行所调度的单元是线程,不是进程。
异步编程演示异步获取百度的html然后异步写入test.txt文件中。
12345678910namespace Test { internal class Program { static async Task Main(string[] args) { HttpClient client = new HttpClient(); string str = await client.GetStringAsync(@"https:\\www.baidu.com"); string fileName = @"F:\test.txt"; await File.WriteAllTe ...
LINQ
Linq表示语言集成查询,它是.Net框架的扩展,允许我们以使用sql查询数据库的类似方法来查询集合。Linq的查询语法有方法语法和查询语法。方法语法是命令式的,查询语法是声明式的。位于System.Linq名称空间。Linq查询可以返回两种类型的结果——可以是一个枚举,它是满足查询参数的项列表;也可以是一个叫标量的单一值,它是满足查询条件的结果的某种摘要形式。
匿名类型学习Linq之前,让我们先来认识一下匿名类型。
12345var student = new { age = 18, name = "张三", major = "数字电路" };
匿名类型的成员类型由编译器推断,只需要在对象初始化语句中初始化即可。注意事项:匿名类型只能用于局部变量,不能用于类成员。必须使用var作为变量类型。编译器为匿名类型创建的属性是只读的。可以使用投影初始化语句来初始化匿名对象(与JS一样):
12345678static v ...
枚举器与迭代器
为什么数组可以被foreach遍历呢?原因是数组可以按需提供一个叫做枚举器的对象,枚举器可以依次返回请求数组中的元素,枚举器知道项的次序并且追踪它在序列中的位置,然后返回请求的当前项。获取对象枚举器的方法是调用对象的GetEnumerator方法。实现GetEnumerator方法的类型叫做可枚举类型。
IEnumerator接口位于System.Collections。实现了IEnumerator接口的枚举器包含3个函数成员:Current、MoveNext以及Reset。Current是返回序列中当前位置项的属性,它是只读的,它返回object类型的引用,我们必须把它转成实际类型的实例。MoveNext是把枚举器位置前进到集合中下一项的方法。它也返回布尔值,指示新的位置是有效位置还是已经超过了序列的尾部,MoveNext必须在第一次使用Current之前调用。Reset是把位置重置为原始状态的方法。
123456789//using System.Collections;static void Main(string[] args) { int[] ...
协变与逆变
大家通常会犯一个错误,就是将派生类型的委托分配给基类型委托的变量,下面来看这个主题叫做可变性,它分为三种——协变、逆变、不变。
协变如果类型参数只用做输出值与构造委托有效性之间的常数关系叫做协变。你也许知道,你可以将派生类型的对象赋值给基类型的变量,这称作类型兼容。
123456789101112131415internal class Program { static void Main(string[] args) { Factory<Cat> catMaker = MakeCat; Factory<Animal> animalMaker = catMaker;//报错 } static Cat MakeCat() { Cat cat = new Cat(); return cat; }}delegate T Factory<T>();class Animal { public int Num ...
泛型
为什么需要泛型大家有没有觉得一个类的成员类型或者一个方法的返回值类型和参数类型一旦写好就不太方便修改,如果一个经常使用的类,它的某个成员类型有时候需要int,有时候需要string,我们需要不停的修改这个类,或者声明一个与其名字相似但成员类型不同的新的类,这样做非常麻烦。另外还有一个函数,它的参数类型有时候需要int,有时候需要double,虽然我们可以进行函数重载,但代码挺多的。为了解决上述问题,提供了新的解决方案——泛型。我们可以使用“类型占位符”书写代码,然后在创建类的实例时知名真实的类型。泛型类型不是类型,而是类型的模板。
泛型类12345678910static void Main(string[] args) { MyClass<int, double> myClass = new MyClass<int, double>() { Value1 = 12 ,Value2 = new double[] { 1,2,3} }; } } p ...
接口
为什么我们需要接口接口是指定一组函数成员而不实现它们的引用类型,只有类和结构可以实现接口。接口是抽象类的进一步抽象。可以很好的帮助我们解决类的耦合。接下来我会一步步推出来为什么要使用接口。
抽象类解耦123456789101112131415internal class Program { static void Main(string[] args) { HuaWei huaWei = new HuaWei(); Man man = new Man(); man.huaWei = huaWei; } } class Man { public HuaWei huaWei { get; set; } } class HuaWei { public void Call() { Console.WriteLine("我 ...
匿名函数
匿名方法是在实例化委托是内联声明的方法。
匿名函数使用位置声明委托变量时作为初始化表达式
组合委托时在赋值语句的右边
为委托增加事件时在赋值语句的右边
匿名函数语法12345678910 internal class Program { static void Main(string[] args) { MyDel del = delegate (string str) { Console.WriteLine(str); }; del(); } } delegate void MyDel(string str);}
匿名函数不会显式声明返回值,但是实现代码必须通过返回一个与委托的返回值相同的值来匹配委托的返回类型。当委托的参数列表不包含out参数并且匿名方法不适用任何参数时可以省略括号。
123MyDel del = delegate { ...
事件
事件是类的成员,是使对象或类具有通知能力的成员。事件的组成:发布者、订阅者、事件处理程序、触发事件。事件订阅本质上是一种以委托类型为基础的约定。
事件相关的说明事件包含了一个私有的委托,但是你无法直接访问委托。事件中可用的操作比委托少,我们只能添加、删除或调用事件处理程序。事件被触发时,它调用委托来一次调用调用列表中的方法。+=、-=是事件唯一允许的操作。委托类型声明:事件和事件处理程序必须有共同的签名和返回类型,它们通过委托类型进行描述。事件处理程序声明:订阅者类中会在事件触发时执行的方法声明。他们不一定是显示命名的方法,还可以是Lambda表达式或匿名方法。事件声明:订阅者必须注册事件才能在事件被触发时得到通知。这是将事件处理程序与事件相连的代码。触发事件的代码:发布者类中“触发”事件并导致调用注册的所有事件处理程序的代码。
创建发布者类12345class Button{ private int Width = 240;//按钮宽度 private int Height = 120;//按钮高度 privat ...
委托
可以认为委托是持有一个或多个方法的对象,但委托与对象不同,可以执行委托,这时委托会执行它所持有的方法。如果学过C/C++可以将委托理解成函数指针的升级版。
初识委托委托与类平级,所以一般声明在类声明的位置,委托的访问性默认是internal。
12345678910internal class Program { static void Main(string[] args) { MyDel del = new MyDel(SayHello); del.Invoke(); } static void SayHello() { Console.WriteLine("Hello world!"); }}delegate int MyDel(int i);
创建委托实例时,可以传入实例方法或者静态方法的方法名。
初始化委托我们已经见到了new的赋值方法
1MyDel del = new MyDel(Ix10);
也可以使用委托赋值的快 ...
Dictionary字典
字典(dictionary)的声明声明字典时,需同时声明字典内的键和值的类型。
1Dictionary<int,string> dic = new Dictionary<int,string>();
字典的读取与增加键和值可以是任何类型,但键必须是唯一的。
123456789class Program { static void Main(string[] args) { Dictionary<int,string> dic = new Dictionary<int,string>(); dic.Add(1, "hi"); dic.Add(2, "你好"); dic[3] = "hello"; Console.WriteLine(dic[3]); }}
字典初始化器1234Dictionary<int,string> dic = new Dic ...