dotnet-sharp 笔记(二)
C#新特性
-
泛型属性
创建属性时可直接使用泛型
// 声明一个泛型属性 public class GenericAttribute<T>:Attribute{} // 使用 [GenericAttribute<string>()] public string Method()=> default;
-
字符串内可插入换行符
$"{\r\n}"
-
原始字符串
三个双引号开头并结尾,可以包含任意特殊字符
-
自动默认结构
struct中所有字段都未显示初始化任何字段都会设置默认值
-
改进型明确赋值
string representation = "N/A"; if ((c != null && c.GetDependentValue(out object obj)) == true) { representation = obj.ToString(); // undesired error } // 优化后 Or, using ?. if (c?.GetDependentValue(out object obj) == true) { representation = obj.ToString(); // undesired error } // 再次优化后 Or, using ?? if (c?.GetDependentValue(out object obj) ?? false) { representation = obj.ToString(); // undesired error }
-
AsyncMethodBuilder
- 对内:关联状态机和状态机执行的上下文,管理状态机的生命周期。
- 对外:构建一个 Task 对象,作为异步方法的返回值,并会触发该 Task 执行的完成或异常。
- 对于async和await的内部改进,多个await调用时按需触发
- 一个 Task 对象,作为异步方法的返回值。
- Create 方法,用来创建 AsyncMethodBuilder。
- Start 方法,用来启动状态机。
- AwaitOnCompleted/AwaitUnsafeOnCompleted 方法,用来将状态机的 MoveNext 方法注册为 async方法 内 await 的 Task 的回调。
- SetResult/SetException 方法,用来标记 Task 的完成状态并触发 Task 的回调。
- SetStateMachine 方法,用来关联状态机,不常用,编译结果也不会调用。
-
CallerArgumentExpression
用另一个实参的文本表示形式替代
-
优化变更
public double CalculateSquare(double value){ return value * value; } // 演变 public double CalculateSquare(doube value)=>value*value; // 再次演变 // in的引入:源兼容的更改而不是二进制的更改 public double CalculateSquare(in double value)=>value*value;
-
静态抽象接口
// 求中间值的静态方法 public static double MidPoint(double left, double right)=>(left+right)/(2.0); // 抽象后 public static T MidPoint(T left, T right)where T:INumber<T> => (left + right)/T.CreateChecked(2);
-
异步流可提供更好的方法
await foreach 来实现异步流
-
不为null的属性
// 当为false时message不能为null,反之则可以为null public static bool IsNullOrWhiteSpace([NotNullWhen(false)] string message)
-
可为空声明
string? name;
-
自动实现属性
// Id不能被序列号,也不能被继承 public clss clzz{ [fidle:NonSerialized] public int Id{get;set;} }
-
INotifyPropertyChanged
属性变更后触发事件
public class Person:INotifyPropertyChanged{ public string FirstName{ get=> _firstName; set{ if(value != _firstName){ _firstName = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FirstName))); } } } private string _firstName; public event PropertyChangedEventHandler PropertyChanged; }
-
语言集成查询(LINQ)
-
相关关键字:from, where, in, order by(descending/descending),select
IEnumerable<string> scoresQuery = from score in scores where score>80 orderby score descending select $"score is {score}";
-
into:创建存储查询的临时表是符
var percentQue = from country in countries let percent = (int) country.Population/10000 // 将group的值存放到countryGroup中 group country by percent into countryGroup where countryGroup.Key >= 20 order by countryGroup.Key select countryGroup;
-
join:级联
多个数据源进行关联或合并
var categoryQuery = from cat in categries join prod in products on cat equals prod.Category select new { Category = cat, Name = prod.Name };
-
子查询
一个表达式出现两次linq语句
var queryGroupMax = from student in students group student by student.Year into studentGroup select new { Level = studentGroup.Key, HighestScore = (from s2 in studentGroup select s2.ExamScores.Average() ).Max() };
-
-
Expression 执行表达式树
-
转换为委托
Expression<Func<int>> add = () => 1+2; // 创建委托 var func = add.Compile(); // 调用委托 var answer = func(); Console.WriteLine(answer);
-
执行幂预算例子
// 创建一个幂是运算的二叉树 BinaryExpression be = Expression.Power(Expression.Constant(2d), Expression.Constant(3d)); // 创建lambda表达式 Expression<Func<double>> le = Expression.Lambda<Func<double>>(be); // 创建委托 Func<double> compiledExpression = le.Compile(); // 执行委托 double result = compiledExpression(); // 输出的结果是8 Console.WriteLine(result);
-
-
Expression各部分方法的说明
// 创建一个委托方法 Expression<Func<int, bool>> exprTree = num => num < 5; // 获得参数树中的第一个参数 ParameterExpression param = (ParameterExpression)exprTree.Parameters[0]; // 获得操作体本身 BinaryExpression operation = (BinaryExpression)exprTree.Body; // 获得传入参数 ParameterExpression left = (ParameterExpression)operation.Left; // 常数体 ConstantExpression right = (ConstantExpression)operation.Right; Console.WriteLine("Decomposed expression: {0} => {1} {2} {3}", param.Name, left.Name, operation.NodeType, right.Value); // Decomposed expression: num => num LessThan 5
-
Expression代码生成转意
// n*(n-1)**(n-2)*(n-3)*(n-4)....*2*1 Func<int, int> factorialFunc = (n) => { var res = 1; while (n > 1) { res = res * n; n--; } return res; }; /////////等同于 //入参为整数:n var nArgument = Expression.Parameter(typeof(int), "n"); //方法内部参数为整数:result var result = Expression.Variable(typeof(int), "result"); // 创建一个标签返回值为int LabelTarget label = Expression.Label(typeof(int)); // 给参数result初始化值为1 var initializeResult = Expression.Assign(result, Expression.Constant(1)); // 创建一个内部方法 var block = Expression.Block( // 等同于 result = result*nArgument Expression.Assign(result, Expression.Multiply(result, nArgument)), // nArgument -= 1 Expression.PostDecrementAssign(nArgument) ); // 在创建一个方法体 BlockExpression body = Expression.Block( // 声明result new[] { result }, // 调用初始化方法 initializeResult, // 创建循环,第一个参数是循环体,第二个参数为中断后输出的值 Expression.Loop( // 判断条件 Expression.IfThenElse( // nArgument>1的时候,执行block,否则跳出 Expression.GreaterThan(nArgument, Expression.Constant(1)), // 正确 block, // 错误时,携带label类型的result跳出 Expression.Break(label, result) ), //返回值 label ) );