zoukankan      html  css  js  c++  java
  • C# 语法糖

     语法糖:指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。

        它可以给我们带来方便,是一种便捷的写法,编译器会帮我们做转换;而且可以提高开发编码的效率,在性能上也不会带来损失。

    语法糖——它不甜吗

    它好甜呐☻☺

    $符号、对象初始值设定项、元组、Linq、Null检查符?.、可爱的var、扩展方法、yield关键字
    1.$符号【字符串插值C#6新特性】的用法
    $符号的作用相当于对String.format()的简化

    //使用Format的写法
    string str2 = string.Format("my name is {0},my age is {1}.", name, age);
    //使用$语法糖的写法
    string str3 = $"my name is {name},my age is {age}.";

    2. 对象初始值设定项 和 匿名对象 ,类型实例化的语法糖 

    利用对象初始值设定项语法,你可为构造函数指定参数或忽略参数(以及括号语法)

    //对象初始化器
    Person p = new Person {
    Name = "andy",
    Age = 24
    };
    //匿名对象
    var p2 = new { Name = "dimo", Age = 24 };
    Console.WriteLine(p.Name);
    Console.WriteLine(p2.Name);
    Cat cat = new Cat { Age = 10, Name = "Fluffy" };
    Cat sameCat = new Cat("Fluffy"){ Age = 10 };

    声明一个List并给list赋初始值——初始值设定项

    List<string> list = new List<string> {"def","OK"};

    3、元组

    //结构Struct
    public struct ValueTuple<T1, T2, T3>: IEquatable<ValueTuple>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple>, IValueTupleInternal, ITuple
    //类class
    public class Tuple<T1> : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple

    数组合并了相同类型的对象,而元组合并了不同类型的对象。

    ValueTuple<int,int> s = (1, 3);//直接使用()声明最方便
    var svar = (1, 3);//括号声明。
    Tuple<int> ne = new Tuple<int>(2);//new 或静态方法Create
    Tuple<int> creat = Tuple.Create<int>(2);//静态方法Create

    4. 集合类各个项的操作Linq。

    我们为了逐个处理集合中的项,需要这么写:

    foreach (string item in list)
    {
    Console.WriteLine(item);
    }

    现在不需要了,这样就可以了

    list.ForEach(a => Console.WriteLine(a));

    在语法糖的光辉照耀下,可以这样:Linq 或 对应方法。

    public class Program
    {
    public static void Main()
    {
    List<string> Sizes = new List<string> { "L", "XL", "XXL" };
    Sizes.ForEach(x => Console.WriteLine(x));
    
    
    //更多使用方法(包括但不限于这些 ,自己挖吧,伙伴们!):
    
    //确定“XL”是否在集合中
    var r1 = Sizes.Contains("XL");
    
    //确定集合中是否包含与条件匹配的元素
    var r2 = Sizes.Exists(x => x == "XL");
    
    //返回集合项中包含“X”的第一个元素
    var r3 = Sizes.Find(x => x.Contains("X"));
    }
    }

    5.??、 ?、 ?: 、?.
    1. 可空类型修饰符(?)
    2. 三元(运算符)表达式(?: )
    例如:x?y:z 表示如果表达式x为true,则返回y;
    如果x为false,则返回z,是省略if{}else{}的简单形式。
    3. 空合并运算符(??)——相当于三目运算符,
    判断是否不为空 x??y 相当于 x!=null?x:y

    最大的用处是将可空类型的值赋给对应的基元类型进行简化。可空类型不可强转对应C#内置类型。

    int? i = 123;
    
    int j = i ?? 0;

    4.NULL检查运算符(?.) 替代原来的 .

    ?[]是索引器的Null检查用法。

    如果 a 的计算结果为 null,则 a?.x 或 a?[x] 的结果为 null。

    如果 a 的计算结果为非 null,则 a?.x 或 a?[x] 的结果将分别与 a.x 或 a[x] 的结果相同。

    int? firstX = null;
    if (points != null)
    {
      var first = points.FirstOrDefault();
      if (first != null)
      firstX = first.X;
    }

    正确倒是正确了,代码取变得难读多了。在C# 6.0中,引入了一个 ?. 的运算符,前面的代码可以改成如下形式:
    int? firstX = points?.FirstOrDefault()?.X;
    从这个例子中我们也可以看出它的基本用法:如果对象为NULL,则不进行后面的获取成员的运算,直接返回NULL
    6. 可爱的var

    var的意义时不必写声明的类型,编译器会根据后面对var的赋值判断它的类型,var的类型一旦确认就不能再改变,它只能作为局部变量使用,不能用做字段也不能用做参数声明。

    例如:

    var writer = new StreamWriter(path);
    
    for(var i=0;i<100;i++){}

    7. 传说中的扩展方法
    1、 扩展类必须为静态类,扩展方法必须为静态方法【静态类中只能有静态方法】
    2、扩展方法的第1个形参开头必须使用 “this” 关键字然后再填写扩展的目标类。
    3、如果需要接收参数则从第2个参数开始算起,第1个参数在真正调用方法时是隐藏的。

    在c#3.5时引入了扩展方法,我们可以在不修改类源码的情况下给类增加实例方法,这个很有意义。它的实质也是一种语法糖的实现

    例如我们给String类扩展一个IsNumber的方法:

    public static class StringExt {
    static private Regex regexNumber = new Regex("\d+");
    static public bool IsNumber(this string input)
    {
    if (string.IsNullOrEmpty(input))
    {
    return false;
    }
    return regexNumber.IsMatch(input);
    }
    }

     扩展方法有两种调用方式

    扩展方法:

    public static class ItemsManagerComponentHelper
    {
    
    public static ItemInfo getItemById(this ItemsManagerComponent self, long itemId)

    调用:

    ItemInfo newFashion0 = ItemsManagerComponentHelper.getItemById(itemsManagerComponent,10);
    ItemInfo newFashion = itemsManagerComponent.getItemById(10);

    ————————————————

    参考链接:https://blog.csdn.net/kone0611/article/details/76056318

    ▲在 java 中没有这样的东西,一个类一旦是 final 的 ,这个类就不能再被添加方法, 但是 C# 能够做到,可以给 sealed 类添加新的方法,这点我还是比较喜欢 c# 的。这就是 C# 中的扩展方法。
    那么什么情况下我们才需要去给一个类写扩展方法呢?
    系统自带的类型,我们无法去修改;
    修改源代码需要较大的精力,而且可能会带来错误;
    我们只是需要一个或者较少的几个方法,修改源代码费时费力;
    被扩展的类是 sealed 的,不能被继承;(就算不是 sealed 的,我们也不能因为需要一个方法而去写一个子类,这样不是面向对象)
    ▲下面是扩展方法的三个要素:(也算是语法规则)
    扩展方法必须处于一个静态类中;
    扩展方法必须是一个静态方法;
    扩展方法的参数列表必须以 this 开头,this 后面紧跟的是被扩展类,然后才是方法需要的参数;
    ▲下面写一下扩展方法的特点
    this 关键字紧跟着的不是参数,而是调用者,调用者后面的参数才是扩展方法真正的参数,在调用时必须传递;
    如果被扩展的类中的实例方法和扩展方法的方法签名相同(扩展方法中方法的签名应该要去掉 this 和调用者参数),则优先调用本类中的实例方法;
    被扩展类(可以是普通类,也可以是接口抽象类)的子类对象可以直接调用父类的扩展方法,也就是说子类也继承了父类的扩展方法;
    这点算是第 3 点的补充,只有被扩展类的本类对象或者子类对象,才能调用扩展方法;
    8. yield关键字定义迭代器方法,返回值必须是IEnumberable等集合接口
    yield return:
    先看下面的代码,通过yield return实现了类似用foreach遍历数组的功能,说明yield return也是用来实现迭代器的功能的。执行完第一个yield再向下执行。

    using static System.Console;
    using System.Collections.Generic;
    class Program
    {
        //一个返回类型为IEnumerable<int>,其中包含三个yield return
        //yield return 定义迭代器方法。
        public static IEnumerable<int> enumerableFuc()
        {
            yield return 1;
            yield return 2;
            yield return 3;
        }
    
        static void Main(string[] args)
        {
            //通过foreach循环迭代此函数
            foreach(int item in enumerableFuc())
            {
                WriteLine(item);
            }
            ReadKey();
        }
    }
    输出结果:
    1
    2
    3

    yield break是用来终止迭代的。
    2.只能使用在返回类型必须为 IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>的方法、运算符、get访问器中。
    这也能说明yield关键字其实是一种语法糖,最终还是通过实现IEnumberable<T>、IEnumberable、IEnumberator<T>和IEnumberator接口实现的迭代功能。

    3.编译的时候自动生成了一个新的类,方法返回了这个新的类。它继承了IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>,这时我们应该已经能猜到这个新的类就是我们没有实现对应的IEnumerator的MoveNext(),和Current属性,但是我们仍然能正常使用这些函数的原因了。

    源码,是痛苦的,又是快乐的,如果没有这痛苦,也就没有了这快乐!
  • 相关阅读:
    CentOS7和Ubuntu18.10下运行Qt Creator出现cannot find -lGL的问题的解决方案
    C++中使用CMake编译管理项目
    C++ std::isnan等函数的使用
    七个开源的 Spring Boot 前后端分离项目,一定要收藏!
    基于Select模型的Windows TCP服务端和客户端程序示例
    简单的C++11线程池实现
    Windows下FFMEPG编译
    MIMO431学习笔记目录
    golang调用海康sdk
    GRPC-go版本
  • 原文地址:https://www.cnblogs.com/erlongxizhu-03/p/12564175.html
Copyright © 2011-2022 走看看