美文网首页csharp
C#6中的新增功能 【Unity3D亲测】

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

作者: su9257_海澜 | 来源:发表于2018-09-30 03:10 被阅读90次

    随着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
    
    

    相关文章

      网友评论

      本文标题:C#6中的新增功能 【Unity3D亲测】

      本文链接:https://www.haomeiwen.com/subject/adlpoftx.html