2.0
泛型
泛型方法、泛型委托、泛型接口
泛型约束(constraints)
default 关键字: default(T);
迭代器(iterator);
可空类型(Nullable Type): int? x; int y = x ?? -1;
匿名方法(Anonymous Method): delegate() { System.Console.Write("Hello, "); };
委托的协变和逆变(covariance and contravariance);
部分类(partial);
静态类(static class);
global:: 全局: global::System.Console.WriteLine(number);
extern alias 别名;
属性Accessor访问控制 : public string X { private|protected get {return _x;}};
友元程序集(Friend Assembly) : [assembly:InternalsVisibleTo("cs_friend_assemblies_2")]让其它程序集访问自己的internal成员;
fixed关键字 : 更好的处理一些非托管的代码:public struct MyArray { public fixed char pathName[128]; };
volatile关键字:表示相关的字可能被多个线程同时访问,编译器不会对相应的值做针对单线程下的优化,保证值在任何时候访问都是最新的;
#pragma warning
用来取消或者添加编译时的警告信息。每个警告信息都会有个编号,如果warning CS01016之类的,使用的时候取CS后面的那个数字,例如:
#pragma warning disable 414, 3021
这样CS414和CS3021的警告信息就都不会显示了。
3.0
匿名类型: var new { Name = "Lawnmower", Price = 495.00 };
类型推断: var z = 1; z就是int
扩展方法:func(this type self, ...)
λ(lambda)表达式: (s)=>{...}
对象和集合的初始化:
自动属性 : public int X { get; set; }
查询表达式 linq: ...
表达式树: Func<int,int> f = x => x + 1;Expression<Func<int,int>> e = x => x + 1;
4.0
针对泛型接口的协变和逆变 :
动态绑定 : dynamic
可选参数 : private void CreateNewStudent(string name, int studentid = 0, int year = 1)
命名参数:指定参数的名字来给值,不按方法参数顺序制定参数值:CreateNewStudent(year:2, name:"Hima", studentid: 4);
并行编程: 主要是库提供
5.0
异步编程 async和await :$黄金技能$
调用方信息 三个Attribute:CallerMemberName、CallerFilePath和CallerLineNumber绑定运算符 : ":=:" 这个没实现!带参数的泛型构造函数 : public class T MyClass : T:class, new(int)这个没实现!支持null类型运算:int x? = null;int y? = x + 40; 和 Myobject obj = null;Myotherobj obj2 = obj.MyProperty ??? new Myotherobj();这个没实现!case支持表达式:switch(myobj){ case string.IsNullorEmpty(myotherobj): .........这个没实现!扩展属性 :[Associate(string)]public static int Zivsoft_ExtensionProperty { get;set;}这个没实现!
1万只草泥马飞奔,实际上就前两个真的实现了!
6.0
主要构造函数:public class user(string name, int age){ ...... }$白银技能$
自动属性赋值:public string name {get;set;} = string.Empty;$黄金技能$
字典初始化器 : public Dictionary<string, string> _users { get; } = new Dictionary<string, string>(){["users"] = "Venkat Baggu Blog"};$白银技能$声明表达式 : if ((var user = _userRepository.Users.FindById(x => x.UserID == userId) != null){return user.City;} # 好像没实现
using静态类:using System.Console; ... WriteLine("");$白银技能$内联out参数定义:if (!int.TryParse(userId, out var id)){return id;} # 好像没实现
在catch块中用await: catch (Exception) { await Logger.Error("exception logging"); };
异常过滤器 : catch (Exception ex) if (ex.InnerException != null) {...}
检查NULL值的条件访问操作符 : var userRank = UserID?.Rank ?? "No Rank";等效于:var userRank = UserID != null ? Rank : "No Rank";$黄金技能$
nameof 运算符 :大概知道了 就是 输出这个 变量的 文字 int x = 2 string.Format("{0}", nameof(x)); // 输出 x
字符串插值 : $"Hello! My name is {person.FirstName} {person.LastName} and I am {person.Age} years old."$黄金技能$
表达式主体方法 : static public string GetX() => $"--{X}--"; 相当于: static public string GetX() { return $"--{X}--"; }$黄金技能$
表达式主体自动属性 : public string FirstName => Name.Split(' ')[0]; 只适用于 只有 get的自动属性$白银技能$
7.0
Out 变量:if (int.TryParse("123", out int value)) { Console.WriteLine(value); } $白银$
基于Tuple的多返回值方法: public (int add, int multiply) Add_Multiply(int int1, int int2) => (int1 + int2, int1 * int2);(此功能还需 nuget 获取 System.ValueTuple才能完整支持)
例2:(string first, string middle, string last) = GetValues();//返回3个字符串
(var first, var middle, var last) = GetValues();//返回给三个var
var (first, middle, last) = GetValues();//返回给3个var,而且还简写
例3:
public void Deconstruct(out int id, out double price) { id = BookID; price = BookPrice; }
Book book = new Book { BookID = 123, BookPrice = 88.88 };//定义
(int id, double price) = book;//这里自动匹配了Deconstruct方法
$黄金技能$该技能后两个例还未验证。
模式匹配 :这个要熟练
// 假如:动物类animals 有 cat dog pig 三种继承
foreach (var a in animals)
{
if (a is Cat { Name is var name }) //类型及属性匹配,is表达式
{
Console.WriteLine($"Name of {nameof(Cat)} is {name}");
}
string sound = "";
switch (a) //匹配switch语句
{
case Dog d when d.Name == "hola":
sound = "woof... hola" + d.BarkLikeCrazy();
break;
case Dog d:
sound = "woof..." + d.BarkLikeCrazy();
break;
case Cat c:
sound = "meow";
break;
case IEnumerable<Animal> l when l.Any():
//TODO: any logic;
break;
case null:
sound = "no animal";
break;
default:
sound = "I'm mute..";
break;
}
Console.WriteLine($"{a.ToString()} - {sound}");
}
本地方法:就是在方法内定义一个只在方法内使用的方法,其使用范围受限,其他和方法没有区别。在方法内有较多重复代码的时候比较有用。$白银技能$
返回引用:看样例
static ref int Max(ref int first, ref int second, ref int third)
{
ref int max = first > second ? ref first : ref second;
return max > third ? ref max : ref third;
}
int a = 1, b = 2, c = 3;
Max(ref a, ref b, ref c) = 4;//这样写法比较诡异,Max返回的是个值引用
// 例2
ref int GetValue(int[] array, int index) => ref array[index];
int[] array1 = { 1, 2, 3, 4, 5 };
ref int x = ref GetValue(array1, 2);
感觉这个技能比较局限,暂定为$铜技能$
以上“多返回值”,“匹配模式”,“本地方法”在vs20017和4.6.1框架下都测试过。返回引用没有测试通过。也许是写法不对。例2的在core20下测试通过。
方法主体使用表达式:看样例$白银技能$
public void PrintName() => Console.WriteLine(firstName); // 常规
private string firstName = string.Empty;
public Person(string name) => firstName=name; //构造函数:新
~Person() => firstName=string.Empty; //析构函数:新
public string FirstName
{
get => firstName; //GET访问器:新
set => firstName = value; //SET访问器:新
}
protected string ControllerName // 下面是一个获取controller的写法,3个?+?? 相当简洁
{
get => ControllerContext?.RouteData?.Values["controller"]?.ToString() ?? "NoController";
}
数值文字:
var intValue = 123_456_000_000; //表示123456000000
var hexValue = 0xAB_CD_EF; //0x表示十六进制
var binValue = 0b1010_1011_1100_1101_1110_1111; //0b表示二进制
$白银-黄铜$(对数学计算来说算白银,数学用的少的就黄铜了)
7.1新特性
1,异步main入口函数:static async Task<int> Main(){...};// 看起来好象是方便启动异步程序……
2,默认文字表达式:Func<string, bool> whereClause = default; // 以前要 default(Func<string,bool>) $简化技能
3,推断元组元素名:var pair = (count, label); // 元素名直接推断和给定变量名一样 "count" and "label" $简化技能
4,新增编译参数:generate reference-only assemblies: /refout and /refonly. // 好象是编译引用放在pdb文件中,以后研究
7.2新特性
1,值类型引用语义:in(指定参数是通过引用传递的,在方法参数上用),ref readonly(只读引用,方法return上用),readonly struct(只读结构体,结构体上用),ref struct(引用结构体,结构体定义上用),readonly ref struct(只读引用结构体,结构体定义上用)。这个风格有点偏向rust(个人觉得!),通过关键字定义来稳定内存数据。最好看看Span<T>连续内存分配这个。
2,命名参数和可选参数:
PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop");
PrintOrderDetails(productName: "Red Mug", sellerName: "Gift Shop", orderNum: 31);
PrintOrderDetails("Gift Shop", 31, productName: "Red Mug");
PrintOrderDetails(sellerName: "Gift Shop", 31, productName: "Red Mug"); //C#7.2 onwards
PrintOrderDetails("Gift Shop", orderNum: 31, "Red Mug"); // C#7.2 onwards
// However, mixed arguments are invalid if used out-of-order.
// 下面是编译错误范例.
// PrintOrderDetails(productName: "Red Mug", 31, "Gift Shop");
// PrintOrderDetails(31, sellerName: "Gift Shop", "Red Mug");
// PrintOrderDetails(31, "Red Mug", sellerName: "Gift Shop");
可选参数:anExample.ExampleMethod(3, ,4)
anExample.ExampleMethod(3, optionalint: 4);
3,private protected访问修饰符:
public class BaseClass{
private protected int myValue = 0;
}
public class DerivedClass1 : BaseClass {
void Access() {
BaseClass baseObject = new BaseClass();
// Error CS1540, because myValue can only be accessed by classes derived from BaseClass.
// baseObject.myValue = 5; // 这里编译错误,不能通过实例访问,只能继承者访问,下面那句可以。
// OK, accessed through the current derived class instance
myValue = 5;
}
}
7.3新特性
先啰嗦一下:vs2017不认7.0+的新特性,要修改语言支持才行,项目-右键-属性-生成-高级-语言版本-最新;
1,泛型约束终于添加了enum 和 delegate:
public static string ToStr<T>(T t) where T : System.Enum //不能直接用enum
public static string ToRun<F>(F f, int i) where F : System.Delegate //不能直接用delegate
public class Multicaster<T> where T : System.MulticastDelegate { } // 这个也可以
以下是大微软原话:
where 子句还可包括 unmanaged 约束。 unmanaged 约束将类型参数限制为名为“非托管类型”的类型。 “非托管类型”不是引用类型,且任何嵌套级别都不包含引用类型字段。 unmanaged 约束使得在 C# 中编写低级别的互操作代码变得更容易。 此约束支持跨所有非托管类型的可重用例程。 unmanaged 约束不能与 class 或 struct 约束结合使用。 unmanaged 约束强制该类型必须为 struct。
2,索引 fixed 字段不需要进行固定。但还是要在unsafe上下文,详细请看官方;$近白银技能,应该也是提高速度用的
3,可能会重新分配 ref 局部变量;$近白银技能,大量循环中使用也许会提高不少速度
ref VeryLargeStruct refLocal = ref veryLargeStruct; // initialization
refLocal = ref anotherVeryLargeStruct; // reassigned, refLocal refers to different storage.
4,stackalloc 数组支持初始值设定项:$白银技能,大量数据操作提高速度还是很有效
int* pArr = stackalloc int[3] {1, 2, 3};
int* pArr2 = stackalloc int[] {1, 2, 3};
Span<int> arr = stackalloc [] {1, 2, 3};
5,Tuples元组支持==和!=操作:对比操作按顺序对比内部数据,有一个对比异常就会短路对比操作。从实例看long和int可对比通过名称不同值顺序一样也可以通过(但是直接命名的名称不同不行,具体如下)$白银技能
(int a, string b) pair = (1, "Hello");
(int z, string y) another = (1, "Hello");
pair == another; //通过. Member names don't participate.
pair == (z: 1, y: "Hello"); //报错: literal contains different member names
6,特性目标支持 Field 类和结构的field:$近白银技能
[field: SomeThingAboutFieldAttribute]
public int SomeProperty { get; set; }
7,方法重载解析?(不知道这样说对不对):static void M(S arg); static void M(in S arg); 这应该是个bug,现在修复了,默认调用没in的,要调用in的就必须显示的用in参数调用。$近白银技能
8,初始化中扩展表达式变量:$黄铜技能
public class B {
public B(int i, out int j) { // 这里out注意!
j = i;
}
}
public class D : B {
public D(int i) : base(i, out var j) { // 这里out!
Console.WriteLine($"The value of 'j' is {j}");
}
}
9,方法重载规则更新(具体请看官方文档):
C# 8.0 新特性(并未最后确定)
1,Nullable reference types 可空引用类型:非可空类型赋值空时会提出警告,但是不会报错。用可空就不会报错。$黄铜技能$
2,Async streams 异步流:$白银技能$ 范围有限
async IAsyncEnumerable<int> GetBigResultsAsync() {
await foreach (var result in GetResultsAsync()) {
if (result > 20) yield return result; } }
3,Ranges and indices 范围和索引:Index 定点索引,Range 类型范围索引 $黄金技能$
//定点索引
Index i1 = 3/*索引开始*/,i2 = ^4/*索引结束*/;
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };//$"{a[i1]}, {a[i2]}" = "3, 6"
//范围索引
var slice = a[i1..i2]; // { 3, 4, 5 }//注意这里最后是5,不是6,上面是6,可能是不含结尾
4,Default implementations of interface members 接口成员的默认实现 $黄金技能$ 接口维护轻松一些。
interface ILogger {
void Log(LogLevel level, string message);
void Log(Exception ex) => Log(LogLevel.Error, ex.ToString()); //默认实现,可不必须实现此接口
}
5,Recursive patterns 递归的模式匹配:$黄金技能$ 但是比较复杂需要多注意(模式匹配都比较复杂)
IEnumerable<string> GetEnrollees() {
foreach (var p in People) {
// p是否Student,将常量模式 false 应用于 Graduated 属性以查看它们是否已毕业,
// 并将模式字符串 name 添加到其 Name 属性中,得到他们的名字(如果非空)。
// 因此,如果 p 是 Student,没有毕业并且具有非空的名字,则返回该名字。
if (p is Student { Graduated: false, Name: string name }) yield return name;
}
}
6,Switch expressions Switch 表达式:$白银$ 主要是简化语法;
var area = figure switch {//计算面积
Line _ => 0,//线无面积
Rectangle r => r.Width * r.Height,//方形规则
Circle c => c.Radius * 2.0 * Math.PI,//圆形规则
_ => throw new UnknownFigureException(figure)//其他异常
};
7,Target-typed new-expressions 已知目标类型的新表达式 $白银$ 简化语法类技能
Point[] ps = { new (1, 4), new (3,-2), new (9, 5) }; // all Points
注意:以上 8.0 均待最后发行后确定