.NET/C# 各版本变化及衍生知识点 C# 1.0/2.0

还是新开一篇吧,因为不光要记录各版本变化,还想把相关知识点衍生出来扩展一下,一天写不完就多几天,这里面知识点非常多。

C# 1.0,对应.NET 1.0/1.1,对应VS 2003,新特性:事件、委托。

C# 2.0,对应.NET 2.0,对应VS 2005,新特性:泛型(Dictionary、List)、匿名、迭代、可空、委托(协变/逆变)、部份类、静态类、属性访问控制

C# 3.0,对应.NET 3.0/3.5,对应VS 2008,新特性:隐式类型的部变量、对象集合初始化、查询表达式、表达式树、分部类和方法、AJAX、LINQ、Entity Framework、ADO.NET、类型推断(var)、自动属性、匿名类型、扩展方法、Lambda表达式

C# 4.0,对应.NET 4.0,对应VS 2010,新特性:dynamic、动态绑定、可选(默认)参数、命名参数、泛型的协变和逆变、互操作性

C# 5.0,对应.NET 4.5,对应VS 2012,新特性:异步编程(async/await)、调用方信息、带参数的泛型构造函数、支持null类型运算、case支持表达式、扩展属性

C# 6.0,对应.NET 4.6,对应VS 2015,新特性:主构造函数、using静态类、属性表达式、方法表达式、枚举参数、null判断、Constructor type parameter inference、内联out、自动属性增强、字符串嵌入值string.Format变成直接"{变量}"、nameof表达式、异常过滤器、catch和finally 中的 await 、无参数的结构体构造函数

一、C#1.0

1、事件、委托

事件就是一个特殊的委托,委托和事件就类似于字段和属性的关系,事件是对委托做了一个封装
事件必須用+=或-=(委託可以清空,事件不能清空)
我们可以将“委托”理解为“方法的抽象”,也就是说定义一个方法的模板,至于这个方法具体是怎么样的,就由方法自己去实现。
        public delegate void SaySomething(string name);
        public event SaySomething Come;
        public void SayHello(string name)
        {
            Console.WriteLine("Hello," + name + "!");
        }
        public void SayNiceToMeetYou(string name)
        {
            Console.WriteLine("Nice to meet you," + name + "!");
        }

        public void test()
        {
            SaySomething sayhello = SayHello;
            SaySomething saynice = SayNiceToMeetYou;
            Come += sayhello;
            Come += saynice;
            Come("张三");
        }

大概理解的是:委托相当于“定义”了一个规范(签名相同),由“继承”的具体方法来“实现”,注册事件相当于依次执行委托,也就是执行那些具体的方法。

因为在项目中没具体用过,所以实在难以理解,只好先这样吧。

二、C# 2.0

1、泛型

 一次编码,多次使用、按需实例化、编译时就可以保证类型安全、不用做类型装换、获得一定的性能提升

泛型类、泛型方法、泛型委托、泛型接口

格式为<T>最常用的就是List<T>和Dictionary<T,T>,具体类型可以用的时候再定。

常用来和装箱/拆箱相比较,泛型可以提高性能(不用装拆箱),指定了类型,在编译时容易发现问题。

private static void DoSomething<T>(T a)
{
    T b = a;
    Console.WriteLine(b);
}
static void Main(string[] args)
{
    DoSomething("A");
    DoSomething(1);
    Console.ReadKey();
}

可以看到,就把T当成是普通的Int或String看待就行,就看具体怎么用

泛型约束:

约束
描述
where T: struct
类型参数必须为值类型。
where T : class
类型参数必须为类型。
where T : new()
类型参数必须有一个公有、无参的构造函数。当于其它约束联合使用时,new()约束必须放在最后。
where T : <base class name>
类型参数必须是指定的基类型或是派生自指定的基类型。
where T : <interface name>
类型参数必须是指定的接口或是指定接口的实现。可以指定多个接口约束。接口约束也可以是泛型的。

 语法就是 WHERE T : 约束,是用来约定这个泛型只能取什么值的

interface IMyInterface
{
}

class Dictionary<TKey, TVal>
    where TKey : IComparable, IEnumerable
    where TVal : IMyInterface
{
    public void Add(TKey key, TVal val)
    {
    }
}

2、匿名方法

在使用委托时创建,本来委托要使用一个专门建的方法。但匿名方法可以直接写方法体(js不是天天这么用么。。。),以后有了lamda就更方便了

        delegate void Del(int x);
        Del d = delegate(int k) { /* ... */ };
        Thread t1 = new Thread (delegate() { Console.Write("Hello, "); } );
        ThreadStart ts1 = new ThreadStart(Method1); //可以简写成下面这种
        ThreadStart ts2 = Method1;

3、迭代器

迭代器的返回类型必须为 IEnumerable、IEnumerator、IEnumerable<T> 或 IEnumerator<T>。迭代器是使用在foreach中的集合

foreach不是for的简写,而是对实现了IEnumerable接口的集合进行遍历

而如果不想实现IEnumerator又想用foreach的话,可以使用yield return,相当于yield return帮我们实现了IEnumerator

迭代器代码使用 yield return 语句依次返回每个元素。yield break 将终止迭代
  public class Persons : IEnumerable
    {
        public IEnumerator GetEnumerator()
        {
            yield return "1";
            Thread.Sleep(1000);
            yield return "2";
            Thread.Sleep(1000);
            yield return "3";
            Thread.Sleep(1000);
            yield return "4";
            Thread.Sleep(1000);
            yield return "5";
            Thread.Sleep(1000);
            yield return "6";
        }
    }
    class program
    {
        static void Main()
        {
            Persons arrPersons = new Persons();
            foreach(string s in arrPersons){
                Console.WriteLine(s);
            }
            Console.ReadLine();
        }
    }

简单的说,迭代器就是foreach,前提条件是IEnumerator,如果没有IEnumerator,就用yield return。

 

4、可空类型

int? i = null;
int j = i ?? 0;

可空类型经常配合数据库的可空字段使用。

int本来是不能赋null的,但用了int?,就可以赋null。

??是简写的一种运算符,相当于 int j = i==null? 0 : Convert.ToInt16(i);

注意,可空类型不能直接赋给值类型(因为有可能null),但反过来是可以的。

5、委托(协变/逆变)

协变针对委托的返回值,逆变针对参数;  逆变粗糙化,协变精细化

比较抽象,只了解了个大概

6、部份类、静态类、属性访问控制

部份类(partial):一个类长太了,分成两个类(可存放在不同地方),编译时视为同一个类

静态类(static):不用实例化就能直接访问,并长驻内存。静态类里只能有静态方法,但静态方法不一定要在静态类中。静态类/方法不能访问非静态类/方法,但非静态类/方法(即普通方法)无此限制。

属性访问控制:get和set前面可以加修饰符来控制访问权限,和类、方法的修饰符一致

原文地址:https://www.cnblogs.com/liuyouying/p/5071271.html