C# 2.0-7.0版本新增功能

C#2.0(VS2005)

(1)泛型:
(2)迭代器
(3)partial类:partial类型定义允许将单个类型拆分为多个文件
(4)可空类型:可空类型允许变量包含未定义的值 例:int? a = null;
(5)匿名方法
(6)命名空间别名限定符(:😃:对访问命名空间成员提供了更多控制。global::别名允许方法可能被代码中的实体隐藏的根命名空间
(7)静态类:若要声明那些包含不能实例化的静态方法的类,静态类就是一种安全而便利的方式
(8)外部程序集别名:通过extern关键字的这种扩展用法引用包含在同一程序集中的同一组件的不同版本
(9)属性访问器可访问性:可以为属性的get和set访问定义不同级别的可访问性
(10)委托中的协变和逆变

C#3.0(VS2008)

隐式类型局部变量(var)
(1) 在隐式类型局部变量声明中,被声明的局部类型是从用于初始化变量的表达式中推断出来的。当局部变量声明指定var作为类型并且在范围内没有名为var的类型时,该声明是隐式类型的局部变量声明。
(2) 注意限制
(1) 声明符必须包含一个初始值设定项,错误案例 var x;
(2) 初始化程序必须是一个表达式 错误案例 var x={1,2,3};
(3) 初始值设定项表达式必须具有不能为空类型的编译时类型 错误案例 var x=null
(4) 局部变量声明不能包含多个声明符 错误案例 var x=x=>x+1;
(5) 初始化不能引用声明的变量本身 错误案例 var x=x++;

扩展方法
扩展方法是可以使用实例方法语法调用的静态方法。实际上,扩展方法使得使用附加方法扩展现有类型和构造类型称为可能。
注意:与扩展方法相比,扩展方法不易发现且功能有限。出于这些原因,建议谨慎使用扩展方法,并且仅在实例方法不可行活不可能的情况下使用。
(1) 声明扩展方法:扩展方法是通过方法的第一个参数上指定关键字this作为修饰符来声明的。扩展方法只能在非泛型、非嵌套的静态类中声明 例:public static class Extensions{ public static int SetTransform(this Transform tran,Vector3 pos,Quaternion q,Vector3 scale){
tran.position = pos;tran.rotation = q;tran.localScale = scale;
}}
(2) 调用:Transform tran; tran.SetTransform(Vector3.zero,Quaternion.identity,Vector.one);

Lambda表达式
C#2.0引入了匿名方法,允许在需要委托值得地方内嵌编写代码块,虽然匿名方法提供了函数式编程语言的大部分表达能力,但匿名方法语法本质上是相当冗长和命令式的。Lambda表达式为编写匿名方法提供了更简洁的函数式语法
一个lambda表达式被写成一个参数列表,(参数)=>{语法块};

匿名类型
C#3.0允许将new运算符与匿名对象初始值设定项一起使用以创建匿名类型的对象。
匿名对象初始值设定项声明匿名类型并返回改类型的实例。匿名类型是直接从object 匿名类型的成员是从用于创建类型实例的对象初始值设定项推断出的一系列读/写属性。具体来说,表单的匿名对象初始值设定项

自动实现的属性
通常,属性是通过简单使用支持字段来实现的
例:private int x;
public int X{get{return x;}set{x=value;}}
自动实现的属性会自动执行此模式。更具体地说,允许非抽象属性声明具有分号访问器主体。两个访问器都必须存在并且都必须有分号主体,但它们可以有不同的可访问性修饰符。当这样指定一个属性时,将自动为该属性生成一个支持字段,并且将实现访问器以读取和写入该支持字段。支持字段的名称是编译器生成的,用户无法访问。
以下声明等效与上面的案例
public int X{get;set;}
由于后备字段不可访问,因此只能通过属性访问器对其进行读取和写入。这意味着自动实现的只读或只写属性没有意义,并且是不允许的。然而,可以不同地设置每个访问者的访问级别。因此,可以像这样模拟具有私有支持字段的只读属性的效果;
public int X{get;private set;}

C#4.0(VS2010)

协变和逆变
一;使用协变和逆变能够实现数组之间、委托实例和方法之间、泛型委托实例之间、泛型接口的变量和泛型类型的对象之间、泛型接口的变量之间的隐式转换;使用协变将允许使用比原指定类型派生程度更大(即更具体的)的类型,使用逆变将允许使用比原指定类型派生程度更小(即更不具体的)的类型;
1.协变和逆变都只支持引用类型,不支持值类型;
2.如果泛型接口或泛型委托的类型参数被声明为协变或逆变,则该泛型接口或泛型委托被称为变体
二:数组只支持协变,即支持派生程度更大的类型的数组隐式转换为派生程度更小的类型的数组:
例:object[] myArray = new string[5];
IComparable[] myOtherArray = new string[5];
1.此操作不是类型安全的,给上述数组添加原数组不兼容的对象时会抛出异常ArrayTypeMismatchException:
//myArray[0] = 10; //此处10会被装箱为object类型,而object类型的对象不能隐式转换为string类型
  2.由于值类型不支持协变和逆变,因此下面的转换是错误的:
//object[] myArray = new int[5]; //IComparable[] myOtherArray = new int[5];
 三、委托支持协变和逆变,为匹配委托类型和方法签名提供更大的灵活性,不仅可以将签名完全匹配的方法分配给委托实例,还可以通过协变将返回值类型与委托类型的返回值类型相比派生程度更大的方法分配给委托实例;通过逆变将参数类型与委托类型的参数类型相比派生程度更小的方法分配给委托实

命名参数和可选参数
方法支持默认值得可选参数,在调用时可以省略这些参数。
例:void A(int a,int b =10){}
调用:A(11);

C#5.0(VS2011)

异步功能
异步功能使用了新两个关键字 :async修饰符和await运算符
用async修饰符标记的方法称为异步方法,这个功能将在异步编程中很有帮助
private async void
btnTest_Click(object sender, EventArgs e)
{
var request = WebRequest.Create(txtUrl.Text.Trim());
var content = new MemoryStream();
Task responseTask = request.GetResponseAsync();
using (var response = await responseTask)
{
using (var
responseStream = response.GetResponseStream())
{
Task copyTask = responseStream.CopyToAsync(content);
//Await操作符暂停方法的执行,直到任务完成。 与此同时, 控件被返回到UI线程。
await copyTask;
}
}
txtResult.Text = content.Length.ToString();
}

C#6.0(VS)

异常过滤器
异常过滤器允许你向异常处理程序添加附加条件。可以在catch块旁边可以加一个when语句,并且只有条件返回true时,catch块才会被执行,
例:
try
{
throw new Exception(“E2”);
}
catch(Exception ex) when (ex.Message == “E1”)
{
Debug.Log(“caught E1”);
}
catch(Exception ex) when (ex.Message == “E2”)
{
Debug.Log(“caught E2”);
}

在 catch 和 finally 块中使用 await
现在可以在catch和finally块中设置等待函数。这在C#6.0之前是不允许的
例:
public void Main()
{
BuggyFunctionAsync();
Console.WriteLine(“done!”);
Thread.Sleep(2000);
}

public async void BuggyFunctionAsync()
{
try { throw new Exception(); }
catch
{
Console.WriteLine(“entering catch block”);
await Task.Delay(1000);
Console.WriteLine(“exiting catch block”);
}
finally
{
Console.WriteLine(“entering finally block”);
await Task.Delay(1000);
Console.WriteLine(“exiting finally block”);
}
}

nameof
有时候我们需要字符串形式的变量名。nameof运算符就是这样做的。它接受一个变量并将变量名转成字符串。
例:
int XP = 1;
Debug.Log(nameof(XP));//输出XP

空条件运算符
假设有一个类A的实例a,我们需要访问实例中的成员属性age。
正常做法是:
if(a!=null) a.age = 100;
在C#6.0中可以编写成
a?.age = 100;
只有不为空才会执行?后面的代码

自动属性初始化
可以在声明属性时提供初始或者默认值(即使是只读的)
例:public int XP{get;set;} = 100;

字符串插值
在string.Format函数中,你可以直接引用变量,而不是将要替换为字符串内的索引标记的参数对象传递。事实上,不需要调用string.Format函数
例如:
void A(){int age = 100;
string s = $“age = {age}”;
}

静态类的“using"语句
如果你有一个静态类,你经常使用它的成员,你可以通过using声明类避免每次都输入类名
例:
using static System.Math;
void A(){
Debug.Log(Max(1,2,4));
}

表达式方法/属性
可以帮你编写简单的单行函数和只读属性,而无需显示的返回类型和大括号
例:public int XP=>100;
public int AA()=>XP;

C# 7.0 VS2017

out 变量
能在变量作为out参数传递的位置声明变量
void A(out int x){ x = 1;}
调用:A(out int x);
由于out变量被直接声明为out参数的实参,编译器通常可以判断它们的类型是什么(除非有冲突的重载),英尺可以使用var而不是类型来声明它们
例如:A(out var x);

元组
用于在一个方法中返回多个值
例1:
声明:(string ,string ,int) TEST(int id){return (“1”,“2”,3); }
使用:var t = TEST(1);
获取元组中的值:t.Item1,t.Item2,t.Item3
例1:修改元组元素的默认名称
声明:(string s1 ,string s2 ,int i1) TEST(int id){return (“1”,“2”,3); }
使用:var t = TEST(1);
获取元组中的值:t.s1,t.s2,t.i1
元组是值类型,它们的元素只是公共的、可变的字段。它们具有值相等性,这意味着如果两个元组的所有元素成对相等(并且具有相同的哈希码),则它们是相等的(并且具有相同的哈希码)

局部函数
可以在函数内部在声明一个局部函数,来自封闭作用域的参数和局部变量在局部函数内部可用
例如:void A(){
B();
void B(){}
}

字面改进
允许_作为数字文字内的数字分割符出现,您可以将它们放在数字之间的任何位置,以提高可读性。它们对值没有影响
例如: int d = 12_11;
此外,引入了二进制文字,因此您可以直接指定位模式,而不必记住十六进制表示法。
var b = 0b1010 _1011_1100_1101_1110_1111 ;

ref返回
可以ref在C#中通过引用传递
例如:ref int Test(int[] array){
return ref arrray[0];
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值