C#6.0新特性笔记

Getter专属赋值

可以在构造函数中,给只有get的属性赋初始值。

class Point
{
public int x { get; }
public Point()
{
x = 1;
}
}

自动属性初始化

可以给自动属性,赋初始化值

class Point
{
public int x { get; set; } = 1;
}

全局静态

可以设置全局静态,然后直接写静态类的方法。

using static System.Console;

namespace FxApp
{
internal class Program
{
private static void Main(string[] args)
{
Read();
}
}
}

全局枚举

可以设置全局枚举,然后直接写枚举属性

using static System.ConsoleColor;

namespace FxApp
{
internal class Program
{
private static void Main(string[] args)
{
var color = Red;
}
}
}

字符串插入

可以使用$来进行字符串插入,替代string.format。全局变量或参数都可插入

internal class Program
{
public static int x { get; set; }
private static void Main(string[] args)
{
string text = $"{x},{args}";
}
}

Expression bodied

可以使用箭头表达式来给方法或属性提供表达式体。注意,表达式体不能有括号。

 internal class Program
{
public string Name => "Chenxy";
public int Sum(int x, int y) => x + y;
private static void Main(string[] args)
{
Program po = new Program();
Console.WriteLine(po.Name); //Chenxy
Console.WriteLine(po.Sum(1, 2)); //3
Console.Read();
}
}

索引值初始化

可以给集合赋初始化值

internal class Program
{
IDictionary<int, string> dict = new Dictionary<int, string>()
{
[1] = "first",
[2] = "second"
};
private static void Main(string[] args)
{
Program po = new Program();
foreach (var item in po.dict)
{
Console.WriteLine(item.Value);
}
Console.Read();
}
}

?.运算符

空值运算符,可以简化判断null的工作

public class Point
{
public int x { get; } = 1;
}
internal class Program
{
public static void Main(string[] args)
{
Point po = null;
//C# 5.0 写法
if (po != null)
{
Console.WriteLine(po.x);
}
//C# 6.0 写法
Console.WriteLine(po?.x);
Console.Read();
}
}

nameof表达式

为了防止重构时忘记修改,可以使用nameof来将一个常量和变量绑定。变量改变时,常量随之改变

internal class Program
{
public static void Main(string[] args)
{
string error = string.Empty;
//C# 5.0
Console.WriteLine("error"); //error
//C# 6.0
Console.WriteLine(nameof(error)); //error Console.Read();
}
}

在此代码中,如果改变 error名称,但不修改nameof(error)名称。则会在编译时提示

异常过滤器

可以在try catch中进行判断,来控制是否进入catch。如果hideError为false,则不会进入catch。

public static void Main(string[] args)
{
bool hideError = false;
try
{
throw new Exception();
}
catch (Exception ex) when (hideError)
{
Console.WriteLine("异常已抛出");
} Console.Read();
}

catch和finally中使用await

可以在catch 和 finally中,使用await。

internal class Program
{
public async static void Main(string[] args)
{
HttpClient client = null;
try
{
var result = await client.GetAsync("");
}
catch (Exception ex)
{
var result = await client.GetAsync("");
}
finally
{
var result = await client.GetAsync("");
} Console.Read();
}
}

Visual Studio 2017

https://zhuanlan.zhihu.com/p/25626653

C#7.0新特性笔记

Out

原先代码中,如果使用Out参数,需要预先定义变量。而C#7中,则可以直接在输出参数中定义变量。

我们也可以直接在参数中,定义var隐式变量。

//VS2015
static void Main(string[] args)
{
int x;
OutMethod(out x);
WriteLine($"X:{x}");
Read();
} //VS2017
static void Main(string[] args)
{
OutMethod(out int x);
WriteLine($"X:{x}");
Read();
}

解构

在调用函数中,可以将参数组合封装到一个类的构造函数中。但是无法通过对象解构成各个组成部分。

通过解构函数,则可以完成这个事情。解构函数可以返回对象的具体确定组件。

例如,我们模拟一个参数组合

public class PathInfo {
public string DirectoryName { get; set; }
public string FileName { get; set; }
public string Extension { get; set; }
public PathInfo(string dname, string fname, string extension)
{
DirectoryName = dname;
FileName = fname;
Extension = extension;
}
}

我们需要从nuget加载 System.ValueTuple这样,才可以使用元组进行解构。

我们如果要使用解构,就需要先定义一个解构函数:Desconstruct

public void Deconstruct(out string dname, out string fname, out string extension)
{
dname = DirectoryName;
fname = FileName;
extension = Extension;
}

需要注意的是,必须使用out,名称可以不一样,他是按照参数顺序返回的。

接下来,现在我们使用解构函数来调用。我们展示三种示例,来进行调用测试。

class Program
{
static void Main(string[] args)
{
PathInfo info = new PathInfo("d", "f", "e"); //示例一:参数内声明。也可以使用var
(string dname, string fname, string extension) = info;
WriteLine($"{dname},{fname},{extension}"); //示例二:声明值初始化。分配现有变量
string dname1, fname1, extension1 = null;
(dname1, fname1, extension1) = info;
WriteLine($"{dname1},{fname1},{extension1}"); //示例三:隐式变量声明
var (dname2, fname2, extension2) = info;
WriteLine($"{dname2},{fname2},{extension2}");
Read();
}
}

跟元组类似的写法,会给每个值进行赋值,只要顺序对应即可。

注意:在示例三种,我们在括号外面声明的var,这样括号内的三个变量类型必须一致。

解构函数,要求圆括号内至少有两个输出变量。如果只有一个是不起作用的,例如

(string dname) = info; //这样是不行的。Deconstruct,如果只有一个方法是不行的。

Deconstruct,可以进行重载。使用的时候,会自动找对应的重载方法。

元组

通过元组可以从一个方法中返回多个值。在C#7.0之前,我们会定义输出参数或者对象集合。

我们可以通过两种方式,来定义元祖。

1.不使用参数名,只填写参数类型。这样会返回 Item1,2,3

2.使用参数名,并填写参数类型。这样会返回Item.参数名

3.直接使用参数名。和2一个效果,但是方便一些。

class Program
{
static void Main(string[] args)
{
PathInfo info = new PathInfo(); var item = info.getEmpInfo();
WriteLine($"{item.Item1},{item.Item2},{item.Item3}"); var item2 = info.getEmpInfo2();
WriteLine($"{item2.a},{item2.b},{item2.c}"); var item3 = info.getEmpInfo3();
WriteLine($"{item3.a},{item3.b},{item3.c}"); Read();
}
} public class PathInfo
{
// 不使用参数名,返回Item1,2,3
public (string, string, string) getEmpInfo()
{
return ("a", "b", "c");
}
// 使用参数名,返回定义参数名
public (string a, string b, string c) getEmpInfo2()
{
return ("a", "b", "c");
}
// 使用指定元素
public (string a, string b, string c) getEmpInfo3()
{
return (a: "a", b: "b", c: "c");
}
}

模式匹配

有时候基类会派生一些子类。我们如果要对每个类实施Eject方法。可以使用多个选择来实现。

AS运算符

使用AS运算符转换并赋值

检查结果是否为null

执行Eject操作

IS运算符

使用IS运算符检查类型

转换类型并为其赋值

执行Eject操作

Cast

显示转换赋值

捕捉可能的异常

执行操作

上述这些方法存在的问题都是语法相当冗长,总要为转换的类提供多个语句

具有IS表达式的模式匹配

C#7.0提供模式匹配,用作一种将测试和赋值合并为单个操作方法。

举个例子,我们在C#7以前,进行类型转换如下。我们使用IS运算符

class Program
{
static void Main(string[] args)
{
Eject(new Woman());
Read();
} static void Eject(People peo)
{
if (peo is Woman)
{
Woman wo = (Woman)peo;
wo.Con();
}
}
} class People {} class Woman : People {
public void Con() {
WriteLine("This is Woman");
}
}

可以看出来,我们需要进行 is,然后进行转换。现在我们使用模式匹配来实现上面代码

static void Eject(People peo)
{
if (peo is Woman wo)
{
wo.Con();
}
}

模式匹配将测试和赋值合并成一个操作了。

Switch语句的模式匹配

使用Switch可以在多个可转换的兼容类型之间时更加重要。

如果我们想添加一个附加条件,可以使用when附加在case子句。

static void Eject(People peo)
{
switch (peo)
{
case Woman wo when wo != null:
wo.Con();
break;
case People pe:
break;
default:
break;
}
}

本地函数

C#7.0允许在一个成员内部完全声明本地函数。来替代Action和Func.

本地函数的作用于域,进在周围函数的内部。关于本地函数有以下几个注意点

1.不允许修饰符

2.不支持重载

3.本地函数可以访问所有变量,包括局部变量

4.本地函数存在整个方法范围内,声明不分前后

bool IsPalindrome(string text)
{
if (string.IsNullOrWhiteSpace(text)) return false;
bool LocalIsPalindrome(string target)
{
target = target.Trim(); // Start by removing any surrounding whitespace.
if (target.Length <= 1) return true;
else
{
return char.ToLower(target[0]) ==
char.ToLower(target[target.Length - 1]) &&
LocalIsPalindrome(
target.Substring(1, target.Length - 2));
}
}
return LocalIsPalindrome(text);
}

通过引用返回

通过ref可以将参数传递给函数来进行更新。

C#7.0除了ref参数外,还可以通过函数返回一个引用。

class Program
{
static void Main(string[] args)
{
int[] result = { 1, 2, 3 };
ref int a = ref Find(result);
a += 1;
WriteLine(result[0]);
Read();
} static ref int Find(int[] sum)
{
return ref sum[0];
}
}

文本改进

C#7.0可以通过下划线来提高可读性。可以放在二进制、十进制、十六进制数字的任意位置

long LargestSquareNumberUsingAllDigits =
0b0010_0100_1000_1111_0110_1101_1100_0010_0100; // 9,814,072,356
long MaxInt64 { get; } =
9_223_372_036_854_775_807; // Equivalent to long.MaxValue

Throw表达式

可以在表达式中,直接抛出异常

public string getEmpInfo( string EmpName)
{
string[] empArr = EmpName.Split(",");
return (empArr.Length > 0) ? empArr[0] : throw new Exception("Emp Info Not exist");
}

异步返回类型

编译器不限制异步方法必须返回 void、Task、Task<T>。

任何可以继承 GetAwaiter   方法的都可以进行返回。

但是,此方法我验证不通过。故此暂时不考虑这个特性。

Expression bodied 增强

C#7.0里面把箭头函数表达式,进行了增强。

我们可以直接在构造函数、析构函数中使用

public class Point
{
public Point() => WriteLine("构造"); ~Point() => WriteLine("释放");
}

$

C#新特性记录的更多相关文章

  1. ES2020新特性记录

    1.可选链操作符 // oldlet ret = obj && obj.first && obj.first.second// newlet ret = obj?.fi ...

  2. C# 9.0 新特性之只读属性和记录

    阅读本文大概需要 2 分钟. 大家好,这是 C# 9.0 新特性系列的第 4 篇文章. 熟悉函数式编程的童鞋一定对"只读"这个词不陌生.为了保证代码块自身的"纯洁&quo ...

  3. 【c#】6.0与7.0新特性介绍记录

    c#发展史 引用地址:https://www.cnblogs.com/ShaYeBlog/p/3661424.html 6.0新特性 1.字符串拼接优化 语法格式:$”string {参数}” 解释: ...

  4. SQL Server 2014 新特性——内存数据库

    SQL Server 2014 新特性——内存数据库 目录 SQL Server 2014 新特性——内存数据库 简介: 设计目的和原因: 专业名词 In-Memory OLTP不同之处 内存优化表 ...

  5. 跨平台的 .NET 运行环境 Mono 3.2 新特性

    Mono 3.2 发布了,对 Mono 3.0 和 2.10 版本的支持不再继续,而且这两个分支也不再提供 bug 修复更新. Mono 3.2 主要新特性: LLVM 更新到 3.2 版本,带来更多 ...

  6. 谈谈我的微软特约稿:《SQL Server 2014 新特性:IO资源调控》

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 撰写经历(Experience) 特约稿正文(Content-body) 第一部分:生活中资源 ...

  7. MySQL5.6 GTID新特性实践

    MySQL5.6 GTID新特性实践 GTID简介 搭建 实验一:如果slave所需要事务对应的GTID在master上已经被purge了 实验二:忽略purged的部分,强行同步 本文将简单介绍基于 ...

  8. Sql Server 2012新特性 Online添加非空栏位.

    我们都知道,Sql Server在一个数据量巨大的表中添加一个非空栏位是比较费心的,缺乏经验的DBA或是开发人员甚至可能鲁莽地直接添加导致阻塞相应业务,甚至可能因为资源欠缺造成实例的全局问题.当然这都 ...

  9. HTML5_01之表单新特性

    1.WebStorm快捷键: Ctrl+Alt+(向下方向键):快速复制当前行 Alt+(向上/下方向键):移动当前行 Ctrl+D:删除当前行 Ctrl+/:快速(取消)注释当前行 Ctrl+Alt ...

随机推荐

  1. Server Error in '/' Application. 报错

    控制面板--管理工具--服务--asp.netstate service 设置为自动,并启动

  2. HTML5对表单的一些有意思的改进

    HTML5对表单进行了许多的改进,在这篇文章中,我选择了其中个人认为很有趣的三个变化:自动聚焦,对button元素的改进,把表单元素与非父元素的form表单挂钩进行简单的介绍. 1. 自动聚焦 自动聚 ...

  3. Vue教程:计算属性computed与侦听器watch(三)

    计算属性computed 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的.在模板中放入太多的逻辑会让模板过重且难以维护.例如: <div id="example" ...

  4. iOS:CALayer(17-12-06更)

    目录 1.CALayer(父类) 2.CAShapeLayer(形状/画布) 3.CAEmitterLayer(粒子发射层) 4.CAGradientLayer(渐变层) 5.CATransformL ...

  5. jQuery 属性操作 - addClass() 和 removeClass() 方法

    实例 向第一个 p 元素添加一个类: $("button").click(function(){ $("p:first").addClass("int ...

  6. redux和react-redux的使用详解

    我自己的理解redux就跟vue中的vuex差不多,都是数据管理器,话不多说,我们从经典的计数器案例开始讲解 使用redux实现计数器 创建如下的react项目,我习惯把每一个模块分块,才有这么多文件 ...

  7. multiprocessing中进程池,线程池的使用

    multiprocessing 多进程基本使用 示例代码1 import time import random from multiprocessing import Process def run( ...

  8. Java中connection的常用方法及其描述是什么

    1. close(), 关闭该数据库连接2. commit(), 提交所有更改内容并释放该Connection对象锁定的资源3. createStatement(), 基于本Connection对象, ...

  9. JS中的Symbol数据类型

    最初JS的6种数据类型: null,undefined,boolean,number,string,object 注意:实际上,array和function都是属于object的子类 ES6中,新增了 ...

  10. collections.Counter类统计列表元素出现次数

    # 使用collections.Counter类统计列表元素出现次数 from collections import Counter names = ["Stanley", &qu ...