虽然现在C# 7才发布不久,并且新的版本和特性还在增加中,但是C# 8.0已经为大家公开了一些未来可能出现的新特性。

*注:以下特性只是计划,可能在将来的正式版本会有一些差异

1.Nullable Reference Types

该特性其实本来计划在C#7.x中就引入,但是却被推迟到了下一个版本中。目的是为了避免引用为null的时候而导致的错误。

其核心思想是允许变量类型定义指定是否可以为它们分配空值:

 IWeapon? canBeNull;
IWeapon cantBeNull;
canBeNull = null;       // no warning
cantBeNull = null; // warning
cantBeNull = canBeNull; // warning

此时当申明可为nullable的对象赋值为null的时候,编译器就不会提示警告。

canBeNull.Repair();       // warning
cantBeNull.Repair(); // no warning
if (canBeNull != null) {
cantBeNull.Repair(); // no warning
}

2.Records

records是一个新的语法糖,它简化了原来创建简单类的过程,通过一条语句就可以创建出一个标准的C# 类。

例如下面的代码:

public class Sword(int Damage, int Durability);

它相对于原来的写法是:

public class Sword : IEquatable<Sword>
{
public int Damage { get; }
public int Durability { get; } public Sword(int Damage, int Durability)
{
this.Damage = Damage;
this.Durability = Durability;
} public bool Equals(Sword other)
{
return Equals(Damage, other.Damage) && Equals(Durability, other.Durability);
} public override bool Equals(object other)
{
return (other as Sword)?.Equals(this) == true;
} public override int GetHashCode()
{
return (Damage.GetHashCode() * 17 + Durability.GetHashCode());
} public void Deconstruct(out int Damage, out int Durability)
{
Damage = this.Damage;
Durability = this.Durability;
} public Sword With(int Damage = this.Damage, int Durability = this.Durability) =>
new Sword(Damage, Durability);
}

上面的代码段可以看出,该类具有只读属性和初始化它们的构造函数。它实现值的比较,并且重写了GetHashCode,以便在基于哈希的集合中使用,如Dictionary 和 Hashtable。

同时我们还看到在倒数第二个方法是一个解构的方法,它允许我们将Record所创建的对象进行解构为一个元组(关于解构的特性,可以参加C#7.0的特性)

var (damage, durability) = sword;

最后的一个With方法可以供我们创建一个不同属性值的Sword副本对象。

var (damage, durability) = sword;

当然,对于With的方法,C# 也提供了一个语法糖写法:

var strongerSword = sword with { Damage = 8 };

3.Default Interface Methods

在以往的C# 语法中,我们都知道一个Interface只能够申明方法体,却不能对其进行实现:

interface ISample
{
void M1(); // allowed
void M2() => Console.WriteLine("ISample.M2"); // not allowed
}

按照以往的写法,我们一般是尝试写一些抽象类来作为替代实现:

abstract class SampleBase
{
public abstract void M1();
public void M2() => Console.WriteLine("SampleBase.M2");
}

但在C# 8.0中可能引入接口的方法实现功能。

4.Asynchronous Streams

C# 目前是已经支持了迭代器( iterators ) 和 异步方法。在C#8.0中打算结合现有的两者,推出异步的迭代器,它将基于异步的 IEnumerable 和 IEnumerator 接口:

public interface IAsyncEnumerable<out T>
{
IAsyncEnumerator<T> GetAsyncEnumerator();
} public interface IAsyncEnumerator<out T> : IAsyncDisposable
{
Task<bool> MoveNextAsync();
T Current { get; }
}

此外,使用异步迭代器还需要IDisposable接口的异步版本:

public interface IAsyncDisposable
{
Task DisposeAsync();
}

接下来,在使用的时候,可能看上去就像下面这样:

var enumerator = enumerable.GetAsyncEnumerator();
try
{
while (await enumerator.WaitForNextAsync())
{
while (true)
{
Use(enumerator.Current);
}
}
}
finally
{
await enumerator.DisposeAsync();
}

当然,这个写法对我们C#的开发人员来说可能还不是太眼熟,因为在传统的迭代器写法上,我们已经习惯了Foreach的写法,因此对于异步迭代器来说,它也会存在对应的一个foreach版本,就如同下面这样:

foreach await (var item in enumerable)
{
Use(item);
}
async IAsyncEnumerable<int> AsyncIterator()
{
try
{
for (int i = 0; i < 100; i++)
{
yield await GetValueAsync(i);
}
}
finally
{
await HandleErrorAsync();
}
}

5.Ranges

这个特性可能相对来说就比较有趣了,它允许我们使用简短的语法来定义一个区间值,比如:

var range = 1..5;

这样就产生了一个表示已声明范围的结构:

struct Range : IEnumerable<int>
{
public Range(int start, int end);
public int Start { get; }
public int End { get; }
public StructRangeEnumerator GetEnumerator();
// overloads for Equals, GetHashCode...
}

在实际的应用过程中,我们可以这样来使用它:

Span<T> this[Range range]
{
get
{
return ((Span<T>)this).Slice(start: range.Start, length: range.End - range.Start);
}
}
foreach (var index in min..max)
{
// process values
}
switch (value)
{
case 1..5:
// value in range
break;
}

这个特性看上去果然非常的good。

6.Generic Attributes

对泛型特性的支持将为需要类型作为参数的属性提供更好的语法。目前,只能使用以下语法将类型传递给特性:

public class TypedAttribute : Attribute
{
public TypedAttribute(Type type)
{
// ...
}
}

当有了泛型特性之后,我们可以尝试这样做:

public class TypedAttribute<T> : Attribute
{
public TypedAttribute()
{
// ...
}
}

  

public TypedAttribute(T value)
{
// ...
}

7.Default Literal in Deconstruction

在C# 7.x中引入了default 默认值和解构的概念。在C# 8中将实现两者的共同作用。

要为C#7中的元组的所有成员分配默认值,必须使用元组赋值语法:

(int x, int y) = (default, default);

通过支持解构语法中的默认文字,以下语法也可以实现相同的功能:

(int x, int y) = default;

8.Caller Argument Expression

在C#5中,引入了CallerMemberName, CallerFilePath and CallerLineNumber特性,方便我们能够获取到有关调用方法的一些信息。

就像CallerMemberName在INotifyPropertyChanged中的应用,对于WPF开发的童鞋就在熟悉不过了:

class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
} private int property; public int Property
{
get { return property; }
set
{
if (value != property)
{
property = value;
OnPropertyChanged();
}
}
}
}

在C#8中可能会引入一个叫做CallerArgumentExpression的特性,它捕获调用方法中的参数:

public Validate(int[] array, [CallerArgumentExpression("array")] string arrayExpression = null)
{
if (array == null)
{
throw new ArgumentNullException(nameof(array), $"{arrayExpression} was null.");
}
if (array.Length == 0)
{
throw new ArgumentException($"{arrayExpression} was empty.", nameof(array));
}
}

9.Target-typed new Expression

这可能也将成为将来常用的一个新特性,它将更加简化在申明时候的类型推断。

比如以往我们申明一个对象是这个样子的:

Dictionary<string, string> dictionary = new Dictionary<string, string>(); // without var keyword
var dictionary = new Dictionary<string, string>(); // with var keyword

但是在C#8中,将简化成这样:

class DictionaryWrapper
{
private Dictionary<string, string> dictionary = new();
// ...
}

Over:

当然距离C#8真是发布可能还要等一段时间,期间可能也会增加一些其他的特性,真正的体验效果还是一起期待8.0的发布吧

C# 8.0的计划特性的更多相关文章

  1. C# 3.0新语言特性和改进(一)

    引言 关于C#3.0的特性,园子里已经有了一大把,可能大家都很熟悉了,虽然本人开发中使用过,但自己还是需要记录一下,总结一下.同时也是后面写Linq知识的基础.希望有兴趣的朋友,可以看看. C# 3. ...

  2. php5.3到php7.0.x新特性介绍

    <?php /*php5.3*/ echo '<hr>'; const MYTT = 'aaa'; #print_r(get_defined_constants()); /* 5.4 ...

  3. paip.php 5.0 5.3 5.4 5.5 -6.0的新特性总结与比较

    paip.php 5.0 5.3 5.4  5.5 -6.0的新特性总结与比较 PHP5的新特性 2 · 对象的参照过渡是默认的(default) 3 · 引入访问属性的限制 3 · 引入访问方法的限 ...

  4. C# 6.0 的新特性

    1. 自动的属性初始化器Auto Property initialzier 之前的方式: public class AutoPropertyBeforeCsharp6 { private string ...

  5. NodeJS 框架 Express 从 3.0升级至4.0的新特性

    NodeJS 框架 Express 从 3.0升级至4.0的新特性 [原文地址:√https://scotch.io/bar-talk/expressjs-4-0-new-features-and-u ...

  6. 相比于python2.6,python3.0的新特性。

    这篇文章主要介绍了相比于python2.6,python3.0的新特性.更详细的介绍请参见python3.0的文档. Common Stumbling Blocks 本段简单的列出容易使人出错的变动. ...

  7. MySQL 8.0 InnoDB新特性

    MySQL 8.0 InnoDB新特性 1.数据字典全部采用InnoDB引擎存储,支持DDL原子性.crash safe,metadata管理更完善 2.快速在线加新列(腾讯互娱DBA团队贡献) 3. ...

  8. Atitit jquery  1.4--v1.11  v1.12  v2.0  3.0 的新特性

    Atitit jquery  1.4--v1.11  v1.12  v2.0  3.0 的新特性 1.1. Jquery1.12  jQuery 2.2 和 1.12 新版本发布 - OPEN资讯.h ...

  9. [转]C# 6.0 的新特性

    本文的内容包括引入C#6.0中的新的语言特性有哪些. 还有已经被引入的代码名称为 “Roslyn”新编译器. 编译器是开放源码的,并且可以从 codeplex 网站的这个地址下载到源代码: https ...

随机推荐

  1. task一个任务结束后执行另一个操作

    //创建一个任务 Task<int> task = new Task<int>(() => { ; //显示进度条遮照层, this.ShowPrograssBar(); ...

  2. redis之PubSub

    前面我们讲了 Redis 消息队列的使用方法,但是没有提到 Redis 消息队列的不足之处,那就是它不支持消息的多播机制. 消息多播 消息多播允许生产者生产一次消息,中间件负责将消息复制到多个消息队列 ...

  3. Apache POI使用指南(HSSFWorkbook生成excel)

    说 明: 官网:http://poi.apache.org/ 由于poi的功能多样,可以生成ppt.word.excel.......,本文就以生成excel为例进行说明,相信聪明的你一定能举一反三 ...

  4. 数据结构(四十七)归并排序(O(nlogn))

    一.归并排序的定义 归并排序(Merging Sort)就是利用归并的思想实现的排序方法.它的原理是假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n ...

  5. java和Jvm目录

    回到占占推荐博客索引 主要介绍java基础知识,非框架类及JVM相关的内容文章 java和Jvm目录 Java~关于开发工具和包包 Java~类,抽象类和接口 Java~时间戳小知识 Java~命名规 ...

  6. 中文预训练模型ERNIE2.0模型下载及安装

    2019年7月,百度ERNIE再升级,发布持续学习的语义理解框架ERNIE 2.0,及基于此框架的ERNIE 2.0预训练模型, 它利用百度海量数据和飞桨(PaddlePaddle)多机多卡高效训练优 ...

  7. 最强中文NLP预训练模型艾尼ERNIE官方揭秘【附视频】

    “最近刚好在用ERNIE写毕业论文” “感觉还挺厉害的” “为什么叫ERNIE啊,这名字有什么深意吗?” “我想让艾尼帮我写作业” 看了上面火热的讨论,你一定很好奇“艾尼”.“ERNIE”到底是个啥? ...

  8. [springboot 开发单体web shop] 3. 用户注册实现

    目录 用户注册 ## 创建数据库 ## 生成UserMapper ## 编写业务逻辑 ## 编写user service UserServiceImpl#findUserByUserName 说明 U ...

  9. 泛微ecology OA系统某接口存在数据库配置信息泄露漏洞

    2漏洞详情 攻击者可通过该漏洞页面直接获取到数据库配置信息,攻击者可通过访问存在漏洞的页面并解密从而获取数据库配置信息,如攻击者可直接访问数据库,则可直接获取用户数据,由于泛微e-cology默认数据 ...

  10. PHP获取当前时间

    PHP获取系统当前时间,有date()可以使用. 但date()当前系统时间是格林威治时间,比我们所在的时区晚了整整8个小时.以前处理这个问题时,只是简单的把获取的当前系统的时间戳加上8个小时的时间, ...