C#6中的新增功能 【Unity3D亲测】

随着Unity2017的普及,使用.NET 4X的开发者也越来越多了,下面笔者给大家介绍一下在C# 6中的新功能主要是怕自己忘记,2333,有些功能还是很实用的~

使用Unity版本2018.2.9f1


有说错或者不准确的地方欢迎大家留言指正


参考资料:

自动属性增强功能

    #region 常规
    public string FirstName0 { get; private set; }
    public string LastName0 { get; private set; }

    public readonly string FirstName1 = "菜鸟";
    public readonly string LastName1 = "海澜";
    #endregion

    #region 自动属性增强功能
    public string FirstName2 { get; }
    public string LastName2 { get; }

    public CSharpSix()
    {
        FirstName2 = "菜鸟";
        LastName2 = "海澜";
    }
    public CSharpSix(string firstName, string lastName)
    {
        if (string.IsNullOrWhiteSpace(lastName))
            throw new ArgumentException(message: "不能是空白", paramName: nameof(lastName));
        FirstName2 = firstName;
        LastName2 = lastName;
    }
    public void ChangeName(string newLastName)
    {
        //LastName2 = newLastName;//报错,因为属性只读
    }
    #endregion

自动属性初始值设定项

    #region 自动属性初始值设定项
    public string FirstName3 { get; } = "菜鸟";
    public string LastName3 { get; } = "海澜";
    #endregion

Expression-bodied 函数成员 这适用于方法和只读属性

    #region Expression-bodied 函数成员   这适用于方法和只读属性
    //还可以在只读属性中使用 expression-bodied 成员:
    public string FullName => $"{FirstName1} {LastName1}";
    //等同于     
    public readonly string FullName1 = "菜鸟海澜";

    //仅限一条可以表示为表达式的语句
    public override string ToString() => $"{FirstName1}, {LastName1}";
    public void LogMessage(string a, string b) => Debug.Log(a + b);
    #endregion

using static

增强功能可用于导入单个类的静态方法。 以前,using 语句将所有类型导入命名空间中
下面的示例中IsNullOrWhiteSpace可直接调用

    #region using static

    //using static 增强功能可用于导入单个类的静态方法。 以前,using 语句将所有类型导入命名空间中
    public void TestUsingStatic(string lastName)
    {

        //使用  using static
        if (IsNullOrWhiteSpace(lastName))
        {
            throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));
        }

        //原有方式
        if (string.IsNullOrWhiteSpace(lastName))
        {
            throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));
        }
    }

    #endregion

可空类型(Nullable)与 Null 条件运算符

示例1

    int? nullIntOne = 3;
    //等同于
    Nullable<int> nullInt_One = new Nullable<int>(3);

    double? num3 = new double?();
    bool? boolval = new bool?();

    int Number_Default; //默认值0
    public int? number_Null;//默认值null

如果number_Null 为null则打印666

       Debug.Log(cSharpSix.number_Null ?? 666);

如果打印则报错:NullReferenceException: Object reference not set to an instance of an object

        cSharpSix = null;
        //报错:NullReferenceException: Object reference not set to an instance of an object
        Debug.Log(cSharpSix.FirstName2);

使用Null 条件运算符不会报错,会打印Null
其中的 【?.】可以分别理解为【?】如果不为Null 【.】就执行

        //不会报错,打印Null   其中的 【?.】可以分别理解为【?】如果不为Null 【.】就执行
        Debug.Log(cSharpSix?.FirstName2);

在委托时的使用

    public Action actionOne;

    public void Test()
    {
        actionOne += CustomAction;

        actionOne?.Invoke();

        //等同于
        if (actionOne != null)
        {
            actionOne();
        }
    }

    public void CustomAction()
    {
        Debug.Log("123");
    }

当然也可以这么写,不过笔者认为这种写法还是少用为好,因为

  • 可读性低,大量使用对其他阅读者将是灾难
        //灾难
        Debug.Log(cSharpSix?.FirstName2==null ? cSharpSix.number_Null?.ToString() : "三元运算菜鸟海澜");
        Debug.Log(cSharpSix?.number_Null?.ToString()??"defualt菜鸟海澜");

而且在文档中对应委托使用Null 条件运算符有这样的描述

这个缓存结果笔者有些不解,难道是让他具有原子性?有知道的大佬可以给我留言,不胜感谢~


字符串内插

可读性提高

    public void LogMessage()
    {
        Debug.Log($"姓{FirstName3}名{LastName3}");

        Debug.LogFormat("姓:{0}名:{1}", FirstName3, LastName3);
    }

也可对字符串使用【:】设置格式
还有一些详细的设置,可参考:$ - 字符串内插


    public void LogDateTime()
    {
        Debug.Log($"现在的时间为{DateTime.Now}");

        Debug.Log($"现在的时间为{DateTime.Now:yyyy-MM-dd hh:mm:ss}");
    }

异常筛选器

如果用于异常筛选器的表达式计算结果为 true,则 catch 子句将对异常执行正常处理。 如果表达式计算结果为 false,则将跳过 catch 子句,直接抛出异常。

老版本写法

    public void CatchException()
    {
        try
        {
            throw new Exception("海澜1");
        }
        catch (Exception ex)
        {
            if (ex.Message == "海澜0")
            {
                Debug.LogWarning("异常0");
            }
            if (ex.Message == "海澜1")
            {
                Debug.LogWarning("异常01");
            }
        }
    }

新版本写法

    public void CatchExceptionWhen()
    {
        try
        {
            throw new Exception("海澜1");
        }
        catch (Exception ex) when (ex.Message == "海澜0")
        {
            Debug.LogWarning("异常0");
        }
        catch (Exception ex) when(ex.Message == "海澜1")
        {
                Debug.LogWarning("异常1");          
        }
    }

优点:使用这个when可以更好的判断一个错误是继续处理还是重新抛出去。按照以前的做法,在catch块内如需再次抛出去,需要重新throw出去,这时的错误源是捕捉后在抛的,而不是原先的,有了when语法就可以直接定位到错误源。

使用异常筛选器的另一种推荐模式是将其用于日志记录例程。 这种用法还会利用当异常筛选器计算结果为 false 时,保留异常引发点的方式。
日志记录方法将是这样一种方法:其参数为无条件返回 false 的异常:

    public void CatchExceptionWhenWithLog()
    {
        try
        {
            throw new Exception("海澜1");
        }
        catch (Exception ex) when (LogException(ex.Message))
        {

        }
        catch (Exception ex) when (ex.Message == "海澜0")
        {
            Debug.LogWarning("异常0");
        }
        catch (Exception ex) when (ex.Message == "海澜1")
        {
            Debug.LogWarning("异常1");
        }
    }

    public bool LogException(string ex)
    {
        Debug.LogWarning($"记录异常信息{ex}");
        return false;
    }

nameof 表达式

    public void TestNameOf(string firstName)
    {
        Debug.Log($"输出{firstName}");

        Debug.Log($"输出{nameof(firstName)}");

        Debug.Log($"输出{nameof(CSharpSix.staticName)}");
    }

打印信息


Catch 和 Finally 块中的 Await

在 catch 和 finally 子句中添加 await 支持的实现细节可确保该行为与同步代码的行为一致

    public async Task TestAwait()
    {
        try
        {
            throw new Exception("菜鸟海澜");
        }
        catch(Exception ex) when (ex.Message.Contains("海澜"))
        {
            await LogExceptionAsync();
        }
        finally
        {
            await CloseConnectionAsync();
        }
    }

    private Task CloseConnectionAsync()
    {
        Debug.Log("CloseConnectionAsync");
        Thread.Sleep(1000);
        return null;
    }

    private Task LogExceptionAsync()
    {
        Debug.Log("LogExceptionAsync");
        Thread.Sleep(1000);
        return null;
    }

索引初始值设定项

笔者现在用的这个版本会报错

    #region 索引初始值设定项
    private Dictionary<int, string> webErrors = new Dictionary<int, string>
    {
        [404] = "Page not Found",
        [302] = "Page moved, but left a forwarding address.",
        [500] = "The web server can't come out to play today."
    };
    #endregion

但是放在方法中不会,估计官方会在后续版本中修复

    public void aaa()
    {
        Dictionary<int,string> webErrors = new Dictionary<int, string>
        {
            [404] = "Page not Found",
            [302] = "Page moved, but left a forwarding address.",
            [500] = "The web server can't come out to play today."
        };
    }

改进了重载解析

现在可以正确的区分 Task.Run(Action)Task.Run(Func<Task>())

    #region 改进了重载解析
    public static Task<int> DoThings()
    {
        return Task.FromResult(666);
    }
    #endregion
        Task<int> result = CSharpSix.DoThings();
        Debug.Log($"结果为{result.Result}");

集合初始值设定项中的扩展 Add 方法

这个感兴趣的同学可以自行查看,不过笔者没发现他的特别便利之处

下面是笔者测试时所有的示例代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Threading.Tasks;

public class TestCSharpSix : MonoBehaviour
{


    void Start()
    {
        var cSharpSix = new CSharpSix();

        Debug.Log(cSharpSix.number_Null ?? 666);

        cSharpSix = null;
        //报错:NullReferenceException: Object reference not set to an instance of an object
        //Debug.Log(cSharpSix.FirstName2);
        //不会报错,打印Null   其中的 【?.】可以分别理解为【?】如果不为Null 【.】就执行
        Debug.Log(cSharpSix?.FirstName2);
        Debug.Log(cSharpSix?.FirstName2 ?? "自定义菜鸟海澜");
        Debug.Log(cSharpSix?.FirstName2 ?? "自定义菜鸟海澜");
        cSharpSix = new CSharpSix();
        //灾难
        Debug.Log(cSharpSix?.FirstName2 == null ? cSharpSix.number_Null?.ToString() : "三元运算菜鸟海澜");
        Debug.Log(cSharpSix?.number_Null?.ToString() ?? "defualt菜鸟海澜");

        cSharpSix.LogMessage();
        cSharpSix.CatchException();
        cSharpSix.CatchExceptionWhen();
        cSharpSix.CatchExceptionWhenWithLog();

        cSharpSix.TestNameOf("菜鸟海澜");

        Task.Run(() => { cSharpSix.TestAwait(); });

        Task<int> result = CSharpSix.DoThings();
        Debug.Log($"结果为{result.Result}");

    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static System.String;
using static System.Linq.Enumerable;
using System.Threading.Tasks;
using System.Threading;

public class CSharpSix
{
    #region 常规
    public string FirstName0 { get; private set; }
    public string LastName0 { get; private set; }

    public readonly string FirstName1 = "菜鸟";
    public readonly string LastName1 = "海澜";
    #endregion

    #region 自动属性增强功能
    public string FirstName2 { get; }
    public string LastName2 { get; }

    public CSharpSix()
    {
        FirstName2 = "菜鸟";
        LastName2 = "海澜";
    }
    public CSharpSix(string firstName, string lastName)
    {
        if (string.IsNullOrWhiteSpace(lastName))
            throw new ArgumentException(message: "不能是空白", paramName: nameof(lastName));
        FirstName2 = firstName;
        LastName2 = lastName;
    }
    public void ChangeName(string newLastName)
    {
        //LastName2 = newLastName;//报错,因为属性只读
    }
    #endregion

    #region 自动属性初始值设定项
    public string FirstName3 { get; } = "菜鸟";
    public string LastName3 { get; } = "海澜";
    #endregion

    #region Expression-bodied 函数成员   这适用于方法和只读属性
    //还可以在只读属性中使用 expression-bodied 成员:
    public string FullName => $"{FirstName1} {LastName1}";
    //等同于     
    public readonly string FullName1 = "菜鸟海澜";

    //仅限一条可以表示为表达式的语句
    public override string ToString() => $"{FirstName1}, {LastName1}";
    public void LogMessage(string a, string b) => Debug.Log(a + b);
    #endregion

    #region using static

    //using static 增强功能可用于导入单个类的静态方法。 以前,using 语句将所有类型导入命名空间中
    public void TestUsingStatic(string lastName)
    {

        //使用  using static
        if (IsNullOrWhiteSpace(lastName))
        {
            throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));
        }

        //原有方式
        if (string.IsNullOrWhiteSpace(lastName))
        {
            throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));
        }
    }

    #endregion

    #region 可空类型

    int? nullIntOne = 3;
    //等同于
    Nullable<int> nullInt_One = new Nullable<int>(3);

    double? num3 = new double?();
    bool? boolval = new bool?();

    int Number_Default; //默认值0
    public int? number_Null;//默认值null

    public Action actionOne;

    public void Test()
    {
        actionOne += CustomAction;

        actionOne?.Invoke();

        //等同于
        if (actionOne != null)
        {
            actionOne();
        }
        Debug.Log("注册成功");
    }

    public void CustomAction()
    {
        Debug.Log("123");
    }

    #endregion

    #region 字符串内插

    public void LogMessage()
    {
        Debug.Log($"姓{FirstName3}名{LastName3}");

        Debug.LogFormat("姓:{0}名:{1}", FirstName3, LastName3);
    }

    public void LogDateTime()
    {
        Debug.Log($"现在的时间为{DateTime.Now}");

        Debug.Log($"现在的时间为{DateTime.Now:yyyy-MM-dd hh:mm:ss}");
    }

    #endregion

    #region 异常筛选器

    public void CatchException()
    {
        try
        {
            throw new Exception("海澜1");
        }
        catch (Exception ex)
        {
            if (ex.Message == "海澜0")
            {
                Debug.LogWarning("异常0");
            }
            if (ex.Message == "海澜1")
            {
                Debug.LogWarning("异常01");
            }
        }
    }
    public void CatchExceptionWhen()
    {
        try
        {
            throw new Exception("海澜1");
        }
        catch (Exception ex) when (ex.Message == "海澜0")
        {
            Debug.LogWarning("异常0");
        }
        catch (Exception ex) when (ex.Message == "海澜1")
        {
            Debug.LogWarning("异常1");
        }
    }
    public void CatchExceptionWhenWithLog()
    {
        try
        {
            throw new Exception("海澜1");
        }
        catch (Exception ex) when (LogException(ex.Message))
        {

        }
        catch (Exception ex) when (ex.Message == "海澜0")
        {
            Debug.LogWarning("异常0");
        }
        catch (Exception ex) when (ex.Message == "海澜1")
        {
            Debug.LogWarning("异常1");
        }
    }

    public bool LogException(string ex)
    {
        Debug.LogWarning($"记录异常信息{ex}");
        return false;
    }

    #endregion

    #region nameof 表达式

    public static string staticName = "静态菜鸟海澜";
    public void TestNameOf(string firstName)
    {
        Debug.Log($"输出{firstName}");

        Debug.Log($"输出{nameof(firstName)}");

        Debug.Log($"输出{nameof(CSharpSix.staticName)}");
    }
    #endregion

    #region Catch 和 Finally 块中的 Await
    public async Task TestAwait()
    {
        try
        {
            Thread.Sleep(1000);
            throw new Exception("菜鸟海澜");
        }
        catch (Exception ex) when (ex.Message.Contains("海澜"))
        {
            await LogExceptionAsync();
        }
        finally
        {
            await CloseConnectionAsync();
        }
    }

    private Task CloseConnectionAsync()
    {
        Debug.Log("CloseConnectionAsync");
        Thread.Sleep(1000);
        return null;
    }

    private Task LogExceptionAsync()
    {
        Debug.Log("LogExceptionAsync");
        Thread.Sleep(1000);
        return null;
    }

    #endregion

    #region 索引初始值设定项

    private List<string> messages = new List<string>
{
    "Page not Found",
    "Page moved, but left a forwarding address.",
    "The web server can't come out to play today."
};

    public void aaa()
    {
        Dictionary<int, string> webErrors = new Dictionary<int, string>
        {
            [404] = "Page not Found",
            [302] = "Page moved, but left a forwarding address.",
            [500] = "The web server can't come out to play today."
        };
    }

    //Dictionary<int, string> webErrors11 = new Dictionary<int, string>
    //{
    //    [404] = "Page not Found",
    //    [302] = "Page moved, but left a forwarding address.",
    //    [500] = "The web server can't come out to play today."
    //};
    #endregion

    #region 改进了重载解析
    public static Task<int> DoThings()
    {
        return Task.FromResult(666);
    }
    #endregion

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,055评论 0 13
  • 前言 最先接触编程的知识是在大学里面,大学里面学了一些基础的知识,c语言,java语言,单片机的汇编语言等;大学毕...
    oceanfive阅读 2,981评论 0 7
  • How do we cure ourselves from the past? When a relationsh...
    minifries阅读 190评论 0 0
  • 月正弯,我与沉寂的夜半一同行走.匆匆错过 被路灯照亮 枯树的舞步,那明黄色的光 四处逃逸,不安地 跳动 模糊了黑暗...
    樗里奕阅读 457评论 0 2