秋天可以种植黄柏吗?

小说:秋天可以种植黄柏吗?作者:顺开道公更新时间:2019-05-25字数:37216

可空引用类型是C#8.0计划新增的一个功能,不过已经发布了预览版本,今天我们来体验一下可空引用类型。

安装

您必须下载Visual Studio 2017 15.5预览版(目前最新发布版本是15.4),下载地址:https://www.visualstudio.com/en-us/news/releasenotes/vs2017-preview-relnotes。

安装Roslyn扩展预览版本:

  1. 下载并解压 Roslyn_Nullable_References_Preview.zip [最新版本 11/15/17];
  2. 关闭所有运行的Visual Studio;
  3. 运行zip根目录中的 .install.bat 脚本(如果需要卸载扩展,可以运行.uninstall.bat脚本);

语法与类型

在语法上,可为空引用类型与可为空值类型使用的语法是一致的,在类型后面追加 ? 即可。

class Person
{
    public string FirstName;   
    public string? MiddleName; 
    public string LastName;
}

我们都知道当初微软在增加可为空值类型的时候,实际是在框架中增加了System.Nullable<>类型,您肯定会问,可为空引用类型以框架中又增加了什么新的类型。

我们来看一个演示:

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(typeof(string?).FullName);
        }
    }

输出结果:

您是否觉得奇怪,怎么输出的是System.String,是的,其实微软在框架中没有加入任何类型,我们Person类型进行编译后,再通过doPeek进行反编译,就明白到底发生了什么。

反编译后的结果:

    internal class Person
    {
        public string FirstName;
        [Nullable]
        public string MiddleName;
        public string LastName;
    }

只是在MiddleName字段上增加了System.Runtime.CompilerServices.NullableAttribute标记。

我们来看一看属性、参数、变量、返回值编译之前与编译之后的比对结果。

属性

    // 编译前:
    public string? MiddleName { get; set; }  
  
    // 编译后:
    [Nullable]
    public string MiddleName { [return: Nullable] get; [param: Nullable] set; }

参数

    // 编译前:
    public Person(string? middleName )
    {
        this.MiddleName = middleName;
    }

    // 编译后:
    public Person([Nullable] string middleName)
    {
      this.MiddleName = middleName;
    }

返回值

    // 编译前:
    public string? DoSomething()
    {
        return null;
    }

    // 编译后:
    [return: Nullable]
    public string DoSomething()
    {
      return (string) null;
    }

变量

    // 编译前:
    string? name;

    // 编译后:
    string name;

这里除了变量,其它的都使用了NullableAttribute标记进行的修饰。

它可以做什么?

通过上面的章节,我们知道,可为空引用类型只是在参数、属性、参数和返回值中使用NullableAttribute标记进行修饰,实际上对程序的正常运行没有任何的影响。那么它可以为我们做什么呢?

表达意图

在C#中不能表达这个变量、参数、字段、属性,返回值等可能为null或不能为null,可为空类型可以帮我们解决这个问题。

    class Person
    {
        public string FirstName;   // 不为null
        public string? MiddleName; // 可能为null
        public string LastName;    // 不为null
    }

这个类型的可以表示每一个人都应该 FristNameLastName ,但是不是每一个人都应该有 MiddleName

编译器检测

可为空引用类型的另一个好处是编译器可以帮助我们检测代码,比如对于直接使用可为空引用类型的属性,编译器会发出警告

    void M(Person p)
    {
        p.FirstName = null;          // 1 WARNING: Cannot convert null to non-nullable reference。
        p.LastName = p.MiddleName;   // 2 WARNING: Possible null reference assignment.
        string s = default(string);  // 3 WARNING: Cannot convert null to non-nullable reference。
        
        if (p.MiddleName != null) 
        {
            WriteLine(p.MiddleName.Length); // ok
        }
        
         WriteLine(p.MiddleName!.Length); // ok
    }
    
    class Person
    {
        public string FirstName;     // 4 WARNING: Non-nullable field "FirstName" is uninitialized.
        public string? MiddleName; 
        public string LastName;      // 5 WARNING: Non-nullable field "LastName" is uninitialized.
    }

编译器会帮我们做以下几点检测:

  1. 如果给非可为空引用类型赋null值或可为空引用类型的值,则会发出警告;
  2. 如果直接使用可为空引用类型,则会发出警告;
  3. 如果从来没有给非可为空引用类型的属性赋值,则会发出警告;
  4. 如果需要直接使用可为空引用类型,需要使用 ! 符号告诉编译器,您已经确认过该值不可能为空。

当然这只是编译器的行为,可以禁用与之相关的警告提示。

总结

空引用类型是一个语法糖,只是在编译器的层面帮我们发现可能发生的问题,对程序的正常运行没有任何作用。

参考资料:

  • https://blogs.msdn.microsoft.com/dotnet/2017/11/15/nullable-reference-types-in-csharp/

  • https://github.com/dotnet/csharplang/wiki/Nullable-Reference-Types-Preview

当前文章:http://780pk.com/news/201904/14/content_87662.html

发布时间:2019-05-25 05:29:01

让专家告诉你什么规格的金丝柳是园林绿化常用 急需一批5公分的红枫去哪购买? 哪里有火棘小苗基地? 日本海棠每平米几棵? 哪里有红梅树苗卖? 北方冬天紫藤会落叶吗? 紫藤在贵州可以种植吗? 紫藤花适宜在东北种植吗? 太疯狂了,这里的樱花树价格低到震撼 龟甲冬青0.8m的市场价是多少?

91662 46015 27454 37299 21754 49258 52563 75178 35203 98738 95088 94001 63552 27131 32578 79151 16844 87029 21323 80824 59422 99509 94173

我要说两句: (0人参与)

发布