图片 15

C#语言各个版本特性(一)

一、c#版本中添加的功能:

第五章 方法

C#2.0 

  • 泛型

  • 部分类型

  • 匿名方法

  • 迭代器

  • 可空类型

  • Getter / setter单独可访问性

  • 方法组转换(代表)

  • Co- and Contra-variance for delegates

  • 静态类

  • Delegate inference

1、方法是一块具有名称的代码

C#3.0 

  • 隐式类型局部变量

  • 对象和收集初始化器

  • 自动实现的属性

  • 匿名类型

  • 扩展方法

  • 查询表达式

  • Lambda表达式

  • 表达树

  • 部分方法

包括:方法体、方法头

C#4.0 

  • 动态绑定

  • 命名和可选参数

  • Generic co- and contravariance

  • 嵌入式互操作类型(“NoPIA”)

局部变量必须被赋值才可以执行下面的操作。实例变量有隐式初始化。有时候,类型推断可以用var关键字,类似于C++当中的auto。用于局部变量。

C#5.0 

  • 异步方法

  • Caller info attributes

C#中,不能在第一个名称的有效范围内去声明另一个同名的本地变量。

C#6.0 

  • Compiler-as-a-service(Roslyn)

  • 将静态类型成员导入命名空间

  • 异常过滤器

  • 在Catch和Finally中使用Await

  • 自动属性初始化器

  • 只读属性的默认值

  • Expression-bodied members

  • Null-conditional operators(空条件运算符,简洁检查)

  • 字符串插值

  • nameof operator

  • 字典初始化器

2、本地常量:局部常量。Const
关键字。Const double PI = 3.1415926; 在编译期决定其值。

C#7.0 

  • out变量

  • 模式匹配

  • 元组

  • 解构

  • 局部函数

  • 数字分隔符

  • 二进制文字

  • 局部引用和引用返回

  • 扩展异步返回类型

  • 表达式的构造函数和finalizers

  • Expression bodied getters and setters

  • throw表达式

3、
参数:形参与实参。参数也有几种:值参数/引用参数。

C#7.1 

  • Async main
  • 默认表达式

 

1.C#1.1代码

图片 1图片 2

 1 using System.Collections;
 2 using System.ComponentModel;
 3 
 4 namespace Chapter01.CSharp1
 5 {
 6     [Description("Listing 1.01")]
 7     public class Product
 8     {
 9         string name;
10         public string Name
11         {
12             get { return name; }
13         }
14 
15         decimal price;
16         public decimal Price
17         {
18             get { return price; }
19         }
20 
21         public Product(string name, decimal price)
22         {
23             this.name = name;
24             this.price = price;
25         }
26 
27         public static ArrayList GetSampleProducts()
28         {
29             ArrayList list = new ArrayList();
30             list.Add(new Product("West Side Story", 9.99m));
31             list.Add(new Product("Assassins", 14.99m));
32             list.Add(new Product("Frogs", 13.99m));
33             list.Add(new Product("Sweeney Todd", 10.99m));
34             return list;
35         }
36 
37         public override string ToString()
38         {
39             return string.Format("{0}: {1}", name, price);
40         }
41     }
42 }

View Code

代码局限:

         
 1>.ArrayList没有提供与其内部内容相关的编译时信息,可以添加任何类型数据。

            2>.代码中为属性设置了公共的get方法,则意味着要添加对应的set方法也是公共的。

           
3>.用于创建属性和变量的代码过于复杂,包括一个私有变量和一个公共方法。

2.C#2.0代码

图片 3图片 4

 1 using System.Collections.Generic;
 2 using System.ComponentModel;
 3 
 4 namespace Chapter01.CSharp2
 5 {
 6     [Description("Listing 1.02")]
 7     public class Product
 8     {
 9         string name;
10         public string Name
11         {
12             get { return name; }
13             private set { name = value; }
14         }
15 
16         decimal price;
17         public decimal Price
18         {
19             get { return price; }
20             private set { price = value; }
21         }
22 
23         public Product(string name, decimal price)
24         {
25             Name = name;
26             Price = price;
27         }
28 
29         public static List<Product> GetSampleProducts()
30         {
31             List<Product> list = new List<Product>();
32             list.Add(new Product("West Side Story", 9.99m));
33             list.Add(new Product("Assassins", 14.99m));
34             list.Add(new Product("Frogs", 13.99m));
35             list.Add(new Product("Sweeney Todd", 10.99m));
36             return list;
37         }
38 
39         public override string ToString()
40         {
41             return string.Format("{0}: {1}", name, price);
42         }
43     }
44 }

View Code

private set{name=value;}

属性可以有公共的get访问器和私有的或者是受保护的set访问器,这有助于控制属性的设置方式。

List<T>强类型集合,可以告知编译器列表中只能包含制定的泛型,试图将一个不同的类型添加到列表中,会造成编译时错误。

3.C#3.0代码

图片 5图片 6

 1 using System.Collections.Generic;
 2 using System.ComponentModel;
 3 
 4 namespace Chapter01.CSharp3
 5 {
 6     [Description("Listing 1.3")]
 7     class Product
 8     {
 9         public string Name { get; private set; }
10         public decimal Price { get; private set; }
11 
12         public Product(string name, decimal price)
13         {
14             Name = name;
15             Price = price;
16         }
17 
18         Product()
19         {
20         }
21 
22         public static List<Product> GetSampleProducts()
23         {
24             return new List<Product>
25             {
26                 new Product { Name="West Side Story", Price = 9.99m },
27                 new Product { Name="Assassins", Price=14.99m },
28                 new Product { Name="Frogs", Price=13.99m },
29                 new Product { Name="Sweeney Todd", Price=10.99m}
30             };
31         }
32 
33         public override string ToString()
34         {
35             return string.Format("{0}: {1}", Name, Price);
36         }
37     }
38 }

View Code

自动实现的属性和简化的初始化大大的简化了代码。(Lambda表达式特性操作同样简捷)

硬编码列表不同的构建方式,由于没有name和price变量可供访问,我们必须在类中处处使用属性,这增强了一致性。

4.C#4.0代码

图片 7图片 8

 1 using System.Collections.Generic;
 2 using System.ComponentModel;
 3 
 4 namespace Chapter01.CSharp4
 5 {
 6     [Description("Listing 1.04 (and more)")]
 7     public class Product
 8     {
 9         readonly string name;
10         public string Name { get { return name; } }
11 
12         decimal? price;
13         public decimal? Price { get { return price; } }
14 
15         public Product(string name, decimal? price = null)
16         {
17             this.name = name;
18             this.price = price;
19         }
20 
21         public static List<Product> GetSampleProducts()
22         {
23             List<Product> list = new List<Product>();
24             list.Add(new Product(name: "West Side Story", price: 9.99m));
25             list.Add(new Product(name: "Assassins", price: 14.99m));
26             list.Add(new Product(name: "Frogs", price: 13.99m));
27             list.Add(new Product(name: "Sweeney Todd", price: 10.99m));
28             list.Add(new Product(name: "Unpriced"));
29             return list;
30         }
31 
32         public override string ToString()
33         {
34             return string.Format("{0}: {1}", name, price);
35         }
36     }
37 }

View Code

1>.构造函数包含多个参数时,全部使用命名参数,将不再需要记住或查找形参在所调用方法的形参列表中的顺序。

new Product(price: 9.99m,name: “West Side
Story”)位置相反也可以构造成功。

2>命名实参与位置实参混合时,要么命名实参位于所有位置实参后面,要么部分位置实参要处于正确的形参列表中位置。

概念:命名实参和可选实参。 通过命名实参,你可以为特定形参指定实参,方法是将实参与该形参的名称关联,而不是与形参在形参列表中的位置关联。 通过可选参数,你可以为某些形参省略实参

注意:命名实参、位置实参、可选实参的区别。

总结:

→C#1,只读属性弱类型集合

→C#2,私有属性赋值方法强类型集合

→C#3,自动实现的属性,增强的集合和对象初始化

→C#4,用命名实参更清晰地调用构造函数和方法。

值类型与值参数是两种不同的概念:值类型就是类型本身包含其值。而值参数是把实参的值复制给形参。

Void mymethod(myclass f1, int f2)

{

F1.val += 5;

F2+= 5;

}

调用: mymethod(a1,a2);

执行过程:

图片 9

方法开始时,系统在栈中为形参分配空间,并从实参复制值。a1为引用类型,所以引用被复制,但指向相同。

在使用引用参数时,必须加关键字 ref。 void
method(ref int val){ xxxx }, 方法调用 method(ref y);//必须使用变量。

举例:

Void mymethod(ref myclass f1,ref int f2)

{

F1.val += 5;

F2+= 5;

}

调用: mymethod(ref a1,ref a2);

执行过程:不会开辟新的内存单元,只是把形参名设置为实参的别名而已。a1与f1,引用相同的位置。

图片 10

引用类型作为值参数和引用参数:

我们修改引用参数的成员时,无论是作为值参数还是引用参数,效果都一样。但,当我们去修改引用类型本身时,那么其作为值参数与引用参数是不同的。

请看下面的图形:

图片 11

图片 12

4、输出参数

需要加关键字 out

Void mythod(out int val);
//形参也是实参的别名,且我们通过方法体之后就会知道你传入的实参的值。方法体内部会对实参赋值。

5、参数数组

前面是一个实参对应一个形参,现在是多个实参对应一个特殊的形参。

关键字:params 比如 void mythod(params
int[] vals){ }

调用: int[] arrays = {1, 2 ,3};
mythod(arrays);

调用时,如果是用值类型传递,即实参是值,数组参数是值类型,实参不受影响。

如果是引用类型传递,即实参是数组名,数组参数是引用类型,实参受方法内部影响。

6、方法重载

方法名称相同,方法特征不同即可。

7、命名参数

给参数命名,这样我们可以以任意顺序调用。

Void mythod(int a, int b, int c);

参数的名字和值:
调用时指定名称和值即可。 Mythod(c:2, a:4, b: 1);

8、可选参数

就是我们在调用时,可以调用这个参数,也可以省略这个参数。这时,必须在声明的时候给参数提供默认值。

Void mythod(int a, int b, int c = 2);

图片 13先是必填参数+ 可选参数+
params 参数。

9、栈帧:就是一个个方法进栈。

  1.  //1、类型推断与var关键字(用于局部变量)
  1.  //2、申明局部常量 const double PI =
    3.1415926;

  2.  //3、基本结构 顺序 选择 循环

  3.  //4、方法调用

  4.  //5、返回值 return x;

  5.  //6、返回语句和void方法
    return;用于void声明的方法

  6.  //7、参数:返回多个值与传入多个值的特殊变量

  1.  //
    实参:初始化形参的表达式或者变量

  2.  //8、值传递与引用传递

  3.  

  4.  MyClass a1 = new MyClass();

  5.  int
    a2 = 10;

  6.  Mythod(a1, a2);

  7.  Mythod1(ref a1, ref a2);

  8.  //9、引用传递必须在方法的申明与调用中都使用ref修饰符

  1.  //实参必须为变量,如果是引用类型变量,可以赋值为一个引用或者null。不会为形参分配内存
  1. //10、输出参数,与引用传递用法基本一致
  1.  int
    a3;

  2.  Mythod2(out a1, out a3);

  3.  //11、参数数组

  4.  //声明时需要加修饰符params,调用时不需要。

  1.  // 1)
    用数组参数初始化堆当中数组

  2.  int
    first = 1, second = 2, third = 3;

  3.  MyClass mc = new MyClass();

  4.  mc.ListInts(first, second,
    third);//调用方法

  5.  // 2)
    用数组作为实参

  6.  int[] myarr = new int[] { 4, 5, 6 };

  7.  mc.ListInts(myarr);

  8.  //12、方法重载:方法名称相同,特征不同。返回值无法区分。

  1.  //13、命名参数:在方法调用的时候,我们可以指定参数名称,这样可以改变实参传入方法的顺序
  1.  int
    result = mc.Cal(c: 2, a: 4, b: 3);

  2.  Console.WriteLine(“result: {0}”, result);

  3.  //14、可选参数 只能是值参数类型。

  1.  //为表名某个参数是可选的,必须在方法声明的时候为参数提供默认值。
  1.  //数据类型:值类型 引用类型。

  2.  //参数类型:值,ref,out,params。

  1.  mc.Cal1(5, 6);//可以搭配命名参数

  2.  mc.Cal1(2,b: 2, c: 8);//命名参数必须放在最后写

  3.  //15、栈帧 栈的调用 递归

第六章 深入理解类

数据成员有:字段、类型、常量

函数成员有:方法、属性、构造函数、运算符、索引器、事件。

属性:主要是对字段的封装,我们可以有选择性的定义某个实例变量。

Int Value

{

Set {Value = value > 100 ? 100 :
value; }

Get{return Value;}

}

当然,我们也可以通过设置
set和get访问器来设置 只读和只写属性。

图片 14

索引器是一组set和get访问器。

图片 15

  1. //1、成员修饰符
    规定:如果有修饰符,必须放在核心声明之前。如果有多个修饰符,顺序可变。
  1. //2、静态实例变量
    类的静态成员与实例成员分开保存

  2. //
    静态实例变量可以在方法中初始化,而C++中的实例变量在
    类外面初始化。而常量成员必须在类中初始化,方法中没有常量成员。

  1.     class D

  2.     {

  3.         int mem1;

  4.         static int mem2;

  5.         public void SetVars(int v1, int v2)

  6.         {

  7.             mem1 = v1;

  8.             mem2 = v2;

  9.         }

  10.         public void Display(string str)

  11.         {

  12.             Console.WriteLine(“{0}:mem1={1},mem2={2}”, str, mem1,
    mem2);

  13.         }

  14.  

  15.     }

  16.  

  17.  

  18. //调用

  19.             D d11 = new D();

  20.             D d22 = new D();

  21.             d11.SetVars(2, 4);

  22.             d11.Display(“d11”);

  23.             d22.SetVars(15, 17); //静态变量已改变,且为共有变量,可以脱离实例化而存在

  1.             d22.Display(“d22”);

  2.             d11.Display(“d11”);

  3.     class X

  4.     {

  5.         static public int A;

  6.         public const int val = 100;//类似于define 必须定义在类型内且初始化。没有
    static const int val = 10;语句。

  7.         static public void PrintValA()//静态函数成员可以访问静态成员变量,但不能访问实例变量

  1.         {

  2.             Console.WriteLine(“A : {0}”,A);

  3.         }

  4.  

  5.         private int Value;//字段:分配内存

  6.         public int MyValue//属性:未分配内存
    (属性会根据是写入还是读取来隐式的调用适当的访问器)

  7.         {

  8.             set

  9.             {

  10.                 Value = value;//属性使用实例变量来存储数据。

  11.             }

  12.             get

  13.             {

  14.                 return Value;

  15.             }

  16.         }

  17.  

  18.         public int myval //自动实现属性

  19.         {

  20.             set;

  21.             get;

  22.         }

  23.         public static int val111 { set; get; }//静态属性

  24.     }

  25. }

  26.  

  27. //调用

  28.             X.A = 10;//静态成员可以在使用的时候,在赋值

  1.             X.PrintValA();

  2.             //成员常量

  3.             Console.WriteLine(“{0}”, X.val);//必须加public这边才能找到它

  4.             //3、属性vs访问器 set与get访问器

  1.             //
    一般属性被用来封装字段,然后调用时,用属性即可。

 

  1.     class A

  2.     {

  3.         public int X = 1;

  4.         public int Y = 2;//设置为public的实例变量可以调用对象初始化语句

  1.         private static Random random;

  2.         static A()//静态构造函数

  3.         {

  4.             random = new Random();//初始化Random

  5.         }

  6.         public int GetRandom()

  7.         {

  8.             return random.Next();

  9.         }

  10.         int val;

  11.        public A() //一定要加修饰符

  12.         {

  13.            val = 10;

  14.         }

  15.         public A(int value)

  16.        {

  17.            val = value;

  18.        }

  19.     }

  20.  

  21. //调用

  22.             //4、构造函数 静态构造函数

  23.             A a11 = new A();

  24.             A a22 = new A();

  25.             Console.WriteLine(“{0}”, a11.GetRandom());

  26.             Console.WriteLine(“{0}”, a22.GetRandom());

  27.             //5、对象初始化语句

  28.             //注意:创建对象的代码必须能够访问要初始化的字段与属性。比如,X与Y
    字段必须什么为public。

  29.             A a33 = new A { X = 2, Y = 3 };//对象初始化语句

  30.             A a44 = new A();

  31.             Console.WriteLine(“a33:x={0},y={1}”, a33.X,a33.Y);

  1.             Console.WriteLine(“a44:x={0},y={1}”, a44.X, a44.Y);
  1.  

  2.             //6、析构函数
    使用.net是不需要为类编写析构函数。假如是win32
    api就需要释放其资源了

  3.             //7、read only
    修饰符/关键字,其用法类似于const,但可以对其实例变量赋值,赋值一般在构造函数中进行。

  1.             //8、this
    关键字,防止实例变量被屏蔽,用于带参的构造函数或者方法中。(它是对当前对象的引用)

 

  1.     class Employee //声明索引器 仿照
    属性,用来为多个数据成员提供get与set属性。

  2.     {

  3.         public string a1;

  4.         public string a2;

  5.         public string a3;

  6.  

  7.         public string this[int index]

  8.         {

  9.             set

  10.             {

  11.                 switch (index)

  12.                 {

  13.                     case 0: a1 = value;break;//这个value是默认的形参

  14.                     case 1: a2 = value;break;

  15.                     case 2: a3 = value;break;

  16.                     default: throw new ArgumentOutOfRangeException(“index”);

  17.                 }

  18.             }

  19.             get

  20.             {

  21.                 switch (index)

  22.                 {

  23.                     case 0: return a1;

  24.                     case 1: return a2;

  25.                     case 2: return a3;

  26.                     default: throw new ArgumentOutOfRangeException(“index”);

  27.                 }

  28.             }

  29.         }

  30.     }

  31.  

  32. //调用

  33.  //9、索引器,用来为多个实例变量提供set与get属性。支持重载,只要参数列表不同就可以。

  1.  

  2.             Employee ee = new Employee();

  3.             ee[0] = “zhu”;

  4.             ee[1] = “xue”;//索引器set访问器的自动调用

  5.             ee[2] = “kui”;

  6.             Console.WriteLine(“ee:{0},{1},{2}”, ee[0], ee[1],
    ee[2]);

  7.     class Person

  8.     {

  9.         public string Name { get; private set; }//属性的访问级别默认为public

  10.         private int a;

  11.         public Person(string name) //一般实例变量默认修饰符为private,所以要想其他类能够找到,必须申明为public,不然只能在类内部自己混。

  1.         {

  2.             Name = name;

  3.         }

  4.     }

  5.  

  6. //调用

  7.             //10、访问器的访问修饰符

  8.             //注意:访问器的访问修饰符比成员的访问级别有更高的限制性

  1.             //访问器的默认修饰符为public。

  2.             Person peron = new Person(“zhuxuekui”);

  3.             //peron.a = 5;
    //错误,a为private属性,访问不到。

  4.             Console.WriteLine(“{0}”, peron.Name);

  5. //11、分步类、分步类型和分步方法

  1. //类似于.h
    和 .cpp 文件。就是说,一个类或者方法可以拆成几部分分别定义。
    类前面加 partial 类型修饰符。