• C# 语法新特性


    下面介绍下C#的新语法,这些新语法使编程更方便快捷(往往一行代码能起到老语法几行功能),同时也更健壮减少异常发生,方便阅读。个人认为很有必要掌握下。

    环境准备

    新建一个Product类 和 ShoppingCart

        public class Product
        {
    		public string Name { get; set; }
    		public string Category { get; set; } = "Waterports";
    		public decimal? Price { get; set; }
    		public Product Related { get; set; }
    		public bool InStock { get; } = true;
    		public bool NameBeginsWithS => Name?[0] == 'S';
    
    		public static Product[] GetProduct()
    		{
    			Product kayak = new Product
    			{
    				Name = "Kayak",
    				Category="Water Craft",
    				Price = 275M
    			};
    			Product lifejacket = new Product
    			{
    				Name = "Lifejacket",
    				Price = 48.95M
    			};
    
    			kayak.Related = lifejacket;
    
    
    			return new Product[] { kayak, lifejacket, null };
    		}
    	}
    
        public class ShoppingCart:IEnumerable<Product>
        {
    		public IEnumerable<Product> Products { get; set; }
    
    		public IEnumerator<Product> GetEnumerator()
    		{
    			return Products.GetEnumerator();
    		}
    
    		IEnumerator IEnumerable.GetEnumerator()
    		{
    			return GetEnumerator();
    		}
    	}
    

    新语法介绍

    • null 条件符(?) 语义:只有当对象不为null时才访问对象属性
        public HomeController
        {
            public ViewResult Index()
            {
                List<string> results = new List<string>();
                foreach (Product p in Product.GetProduct())
                {
                    string name = p?.Name ?? "<No Name>";
                    decimal? price = p?.Price ?? 0;
                    string relatedName = p?.Related?.Name ?? "<None>";
                    results.Add(string.Format($"Name:{name},Price{price},Related:{relatedName}"));
                }
                return View(results); 
            }
        }
    
    • null 合并符(??) 语义:当??操作符左侧为null则返回右侧值,否则放回左侧。
        decimal? price = p?.Price ?? 0;
    
    • 属性设置初始值,在声明属性时可以为属性设置初始值
        public string Category { get; set; } = "Waterports";
    
    • 设置read-only属性初始值(有两种方法,另一种在构造函数中设置)
        public bool InStock { get; } = true;
    
    • 字符串中插入变量值,这种时字符串拼接更简单,格式$+字符串
        $"Name:{name},Price{price},Related:{relatedName}"
    
    • 对象和集合的初始化
            //对象初始化  
            Product kayak = new Product
            {
                Name = "Kayak",Category="Water Craft",Price = 275M
            };  
            //数组类初始化  
            string[] names = new string[] { "Bob", "Joe", "Alice" };  
            //字典初始化  
            Dictionary<string, Product> products = new Dictionary<string, Product>
            {
                ["Kayak"]=new Product { Name = "Kayak",Category = "Water Craft"},
                ["Lifejacket"]=new Product { Name = "Lifejacket", Category = "Water Craft" }
            };
    
    • 类型检测符(is) 分析if(data[i] is decimal d)如果data[i]的类型是decimal则返回true并给d变量赋值,在switch语句中同样可以使用
        public ViewResult Total()
            {
                object[] data = new object[] { 275M, 29.95, "apple", "orange", 100, 10 };
                decimal total = 0;
                for(int i = 0; i < data.Length; i++)
                {
                    if(data[i] is decimal d)
                    {
                        total += d;
                    }
                }
                return View($"Total:{total:C2}");
            }
    
    • 扩展方法,通过扩展方法为现有类型添加方法,使调用更方便(注意:1.类为静态类,2方法为静方法 3.第一个参数 this 被扩展类型)
        public static class ShoppingCartExtension
        {
            public static decimal TotalPrices(this ShoppingCart cartParam)
            {
                decimal total = 0;
                foreach(Product prod in cartParam.Products)
                {
                    total += prod?.Price ?? 0;
                }
                return total;
            }
        }
    
    • 应用接口的扩展方法,(建议最好创建接口的扩展方法可以复用)
        public static class ShoppingCartExtension
        {
            public static decimal TotalPrices(this IEnumerable<Product> products)
            {
                decimal total = 0;
                foreach (Product prod in products)
                {
                    total += prod?.Price ?? 0;
                }
                return total;
            }
        }
    
    
    • 使用Lambde表达式表达条件,这样调用端更灵活
        public static class ShoppingCartExtension
        {
            //过滤表达式
            public static IEnumerable<Product> Filter(this IEnumerable<Product> productEnum, Func<Product, bool> selector)
            {
                foreach (Product prod in productEnum)
                {
                    if (selector(prod))
                    {
                        yield return prod;
                    }
                }
            }
        }
    
    

    调用更灵活

        //根据name过滤
        IEnumerable<Product> ProductsbyName =Product.GetProduct().Filter(p => p?.Name?[0] == 'S');
        //或者根据价格过滤
        IEnumerable<Product> ProductsbyPrice =Product.GetProduct().Filter(p => (p?.Price ?? 0) > 30);
    
    • Lambda初始化属性或函数
        //初始化属性
        public bool NameBeginsWithS => Name?[0] == 'S';
        //初始化函数
        public ViewResult ProductsName() => View(Product.GetProduct().Select(p => p?.Name));
    
    • 异步调用asyncawait
            public async static Task<long?> GetPageLength2()
            {
                HttpClient client = new HttpClient();
                var httpMessage = await client.GetAsync("https://baidu.com");
    
                return httpMessage.Content.Headers.ContentLength;
            }
    

    在调用该方法

            public async Task<ViewResult> GetPageLength()
            {
                long? length = await AsyncMethods.GetPageLength2();
                return View($"Length:{length}");
            }
    
    • nameof()获取表达式的变量的字符串形式(为当前变量名添加双引号""),这样避免hard code忘了更新。
        public ViewResult Products()
            {
                var products = new[] {
                    new {Name="Kayak",Price=275M},
                    new {Name="Lifejacket",Price=48.95M},
                    new {Name="Soccer ball",Price=19.50M},
                    new {Name="Corner flag",Price=34.95M},
                };
                //return View(products.Select(p => $"Name:{p.Name},{Price:{p.Price}"));
                //同上 避免更改了属性名忘记更改 hard code`Name`和`Price`
                return View(products.Select(p => $"{nameof(p.Name)}:{p.Name},{nameof(p.Price)}:{p.Price}"));
            }
    
  • 相关阅读:
    Spring shiro 初次使用小结
    Spring data Redis
    Redis 学习相关的网站
    Spring依赖注入 — util命名空间配置
    添加至数据库的中文显示问号
    freemarker的classic_compatible设置,解决报空错误
    HTTP协议
    Maven添加本地Jar包
    java中的字符串分割函数
    读取文件方法大全
  • 原文地址:https://www.cnblogs.com/LoveTomato/p/9923134.html
Copyright © 2020-2023  润新知