带你了解 C# 每个版本新特性

本文详述了C#从1.0到7.0的主要版本特性,包括泛型、分部类、静态类、可空类型、迭代器、匿名方法等。每个版本的关键特性如C#2.0的泛型、C#3.0的Linq、C#5.0的异步处理等,都在文中进行了详细介绍,旨在帮助开发者更好地理解和应用C#语言。
摘要由CSDN通过智能技术生成

上学时学习C#和.NET,当时网上的资源不像现在这样丰富,所以去电脑城买了张盗版的VS2005的光盘,安装时才发现是VS2003,当时有一种被坑的感觉,但也正是如此,让我有了一个完整的.NET的学习生涯。

一直都认为学习语言应该系统的进行学习,了解每一个版本的新增特性,才能在实际应用中做到有的放矢。最近发现团队中有不少人虽然用着最新的技术,但知识储备还停留在一个比较初始的状态,这样在编码过程中会走不少弯路。

本文梳理下C#从1.0到7.0版本的一些常用特性,对于不常用的或者我没有用到过的一些特性,会列出来,但不会做详细描述。另外C#8.0现在还没有正式推出,并且目前我们也只是在使用dotNet Core2.1,所以C#8.0本文也不会涉及。

C#1.X

C# VS版本 CLR版本 .NET Framework
1.0 VS2002 1.0 1.0
1.1 VS2003 1.1 1.1

在C#1.0或1.1版本中,从语言的角度就是基本的面向对象的语法,可以说任何一本C#语言的书籍都包含了C#1.X的所有内容。

如果您已经在使用C#语言编写代码,那么C#1.X的相关知识应该已经掌握。基础语法部分这里就不再赘述了。

C#2.0

C# VS版本 CLR版本 .NET Framework
2.0 VS2005 2.0 2.0

2.0中对应VS2005我用的也不多,因为很快就被VS2008替代了,不过在语言方面却带来了很多新的东西。

泛型

C#2中最重要的一个特性应该就是泛型。泛型的用处就是在一些场景下可以减少强制转换来提高性能。在C#1中就有很多的强制转换,特别是对一些集合进行遍历时,如ArrayList、HashTable,因为他们是为不同数据类型设计的集合,所以他们中键和值的类型都是object,这就意味着会平凡发生装箱拆箱的操作。C#2中有了泛型,所以我们可以使用List 、Dictionary 。泛型能够带来很好的编译时类型检查,也不会有装箱拆箱的操作,因为类型是在使用泛型的时候就已经指定了。

.NET已经通过了很多的泛型类型供我们使用,如上面提到的List ,Dictionary ,我们也可以自己来创建泛型类型(类、接口、委托、结构)或是方法。在定义泛型类型或时可以通过定义泛型约束来对泛型参数进行限制,更好的使用编译时检查。泛型约束是通过关键字where来实现的,C#2中的泛型约束有4种:

  • 引用类型约束:确保类型实参是引用类型,使用where T:class来表示;

  • 值类型约束:确保类型实参是值类型,使用where T:truct来表示;

  • 构造函数类型约束,使用where T:new()来表示;

  • 转换类型约束:约束类型实参是另外的一种类型,例如:where T:IDisposable 。

分部类(Partil)

分部类可以允许我们在多个文件中为一个类型(class、struct、interface)编写代码,在Asp.Net2.0中用的极为广泛。新建一个Aspx页面,页面的CodeBehind和页面中的控件的定义就是通过分部类来实现的。如下:

public partial class _Default : System.Web.UI.Page 
public partial class _Default 

分部类使用关键字partial来定义,当一个类中的代码非常多时,可以使用分部类来进行拆分,这对代码的阅读很有好处,而且不会影响调用。不过现在我们前后端分离,后端代码要做到单一职责原则,不会有很多大的类,所以这个特性很少用到。

静态类

静态类中的公用方法必须也是静态的,可以由类名直接调用,不需要实例化,比较适用于编写一些工具类。如System.Math类就是静态类。工具类有一些特点,如:所有成员都是静态的、不需要被继承、不需要进行实例化。在C#1中我们可以通过如下代码来实现:

//声明为密封类防止被继承 
public sealed class StringHelper
{
    //添加私有无参构造函ˉ数防止被实例化,如果不添加私有构造函数 
    //会自动生成共有无参构造函数 
    private StringHelper(){};
    public static int StringToInt32(string input)
    {
        int result=0;
        Int32.TryParse(input, out result);
        return result;
    }
}

C#2中可以使用静态类来实现:

public static class StringHelper
{
    public static int StringToInt32(string input)
    {
        int result=0;
        Int32.TryParse(input, out result);
        return result;
    }
}

属性的访问级别

在C#1中声明属性,属性中的get和set的访问级别是和属性一致,要么都是public要么都是private,如果要实现get和set有不同的访问级别,则需要用一种变通的方式,自己写GetXXX和SetXXX方法。在C#2中可以单独设置get和set的访问级别,如下:

private string _name;
public string Name
{
    get { return _name; }
    private set { _name = value; }
}

需要注意的是,不能讲属性设置为私有的,而将其中的get或是set设置成公有的,也不能给set和get设置相同的访问级别,当set和get的访问级别相同时,我们可以直接设置在属性上。

命名空间别名

命名空间可以用来组织类,当不同的命名空间中有相同的类时,可以使用完全限定名来防止类名的冲突,C#1中可以使用空间别名来简化书写,空间别名用using关键字实现。但还有一些特殊情况,使用using并不能完全解决,所以C#2中提供了下面几种特性:

  • 命名空间修饰符语法

  • 全局命名空间别名

  • 外部别名

我们在构建命名空间和类的时候,尽量避免出现冲突的情况,这个特性也较少用到。

友元程序集

当我们希望一个程序集中的类型可以被外部的 某些 程序集访问,这时如果设置成Public,就可以被所有的外部程序集访问。怎样只让部分程序集访问,就要使用友元程序集了,具体参考之前的博文《C#:友元程序集(http://blog.fwhyy.com/2010/11/csharp-a-friend-assembly/)》

可空类型

可空类型就是允许值类型的值为null。通常值类型的值是不应该为null的,但我们很多应用是和数据库打交道的,而数据库中的类型都是可以为null值的,这就造成了我们写程序的时候有时需要将值类型设置为null。在C#1中通常使用”魔值“来处理这种情况,比如DateTiem.MinValue、Int32.MinValue。在ADO.NET中所有类型的空值可以用DBNull.Value来表示。C#2中可空类型主要是使用System.Nullable 的泛型类型,类型参数T有值类型约束。可以像下面这样来定义可空类型:

Nullable<int> i = 20;
Nullable<bool> b = true;

C#2中也提供了更方便的定义方式,

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值