• 【从头构筑C#知识体系】1.7 运算符和表达式


    【系列文章目录】



    前言

    本篇介绍运算符与表达式

    【C#文档——委托】


    一、什么是运算符与表达式

    1.定义

    先看看文档里的描述

    表达式是运算符和操作数构成的序列。

    而对于运算符文档中并没有给出一个统一的定义而是给出了几种运算符类型

    所以只能在网上搜索一下了并结合例子来看了

    在百度百科我找到了运算符的定义:

    用于执行程序代码运算,会针对一个以上操作数项目来进行运算。

    结合文档中的例子

    • 运算符是组成表达式运算方式的符号
    • 而表达式是由数据与运算符组成的

    2.理解表达式与运算符

    虽然表达式与运算符的定义理解起来有些晦涩,但是实际上他们是很简单的

    举个例子马上就能理解

    int i = 0; 
    
    • 1

    其中 i0 就是数据, = 就是运算符
    而这一行代码就是一个表达式

    这样的表达式在我们写代码的时候经常用到

    二、运算符

    1.运算符类型

    文档中告诉我们运算符有以下类型

    • 算术运算符:将对数值操作数执行算术运算
    • 比较运算符:将比较数值操作数
    • 布尔逻辑运算符:将对 bool 操作数执行逻辑运算
    • 位运算符和移位运算符:将对整数类型的操作数执行位运算或移位运算
    • 相等运算符:将检查其操作数是否相等

    其中位运算符移位运算符在实际使用中,相对少见一些
    其他运算符我们都很常用

    2.运算符优先级

    文档中指出:

    在包含多个运算符的表达式中,先按优先级较高的运算符计算,再按优先级较低的运算符计算。

    那么运算符的优先级是什么样的呢?

    运算符类别或名称
    x.y、f(x)、a[i]、x?.y、x?[y]、x++、x–、x!、new、typeof、checked、unchecked、default、nameof、delegate、sizeof、stackalloc、x->y主要
    +x、-x、x、~x、++x、–x、^x、(T)x、await、&&x、*x、true 和 false一元
    x…y范围
    switch、withswitchwith 表达式
    x * y、x / y、x % y乘法
    x + y、x – y加法
    x << y、x >> y移位
    x < y、x > y、x <= y、x >= y、is、as关系和类型测试
    x == y、x != y相等
    x & y布尔逻辑 AND 或按位逻辑 AND
    x ^ y布尔逻辑 XOR 或按位逻辑 XOR
    xy
    x && y条件“与”
    x || y条件“或”
    x ?? yNull 合并运算符
    c ? t : f条件运算符
    x = y、x += y、x -= y、x *= y、x /= y、x %= y、x &= y、x |= y、x ^= y、x <<= y、x >>= y、x ??= y、=>赋值和 lambda 声明

    3.运算符结合性

    当运算符的优先级相同,运算符的结合性决定了运算的执行顺序:

    • 左结合运算符按从左到右的顺序计算。
      除赋值运算符和 null 合并运算符外,所有二元运算符都是左结合运算符
      例如,a + b - c 将计算为 (a + b) - c。
    • 右结合运算符按从右到左的顺序计算。
      赋值运算符、null 合并运算符、lambda 和条件运算符是右关联 运算符 ?:
      例如,x = y = z 将计算为 x = (y = z)。

    运算符与数学中的运算符类似
    当我们需要改变计算顺序时
    可以为需要优先计算的内容加上()

    int a = 13 / 5 / 2;
    int b = 13 / (5 / 2);
    Console.WriteLine($"a = {a}, b = {b}");  // output: a = 1, b = 6
    
    • 1
    • 2
    • 3

    4.运算符重载

    文档中指出

    通常可以重载这些运算符,也就是说,可以为用户定义类型的操作数指定运算符行为。

    例如Unity中的Vector3就是靠运算符重载实现的两个向量相加减

    运算符重载的方式为

    运算符表示法函数表示法
    op xoperator op(x)
    x opoperator op(x)
    x op yoperator op(x,y)

    例如:

    public struct Money
    {
        public int value;
        public static int operator *(Money x, Money y)
        {
            return x.value + y.value;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这样就实现了一个*的运算符重载

    需要注意的是,运算符重载一定要写在你定义的数据结构(类、结构体)内部,也就是说

    public struct Money{
        public int value;
    }
    
    public static int operator *(Money x, Money y)
    {
        return x.value + y.value;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这样的定义方式是错误的

    三、表达式

    1.常用表达式类型

    常用表达式类型包括

    • 赋值
    • 加减
    • 逻辑判断
    • 调用
    • 查询(LINQ,C#1.0没有)
    • Lambda 表达式(C#1.0没有)

    2.表达式树 (C#)

    【C#文档——表达式树】

    一颗树中,所有叶节点的元素值都是数字,而所有父节点(即有子节点的节点)的元素值都是运算符。

    因为Unity的IL2CPP不支持表达式树,所以我基本没有用过表达式树,就不多介绍了。


  • 相关阅读:
    Sentinel
    分布式数据库 Join 查询设计与实现浅析
    CSS3 新增属性-边框圆角-文字阴影-盒子阴影
    typescript43-类型兼容性说明
    Android类加载
    四、支付宝支付对接 - SDK开发、业务对接、支付回调、支付组件(2)
    Golang cron 定时器和定时任务
    四、Vue
    华为云云耀云服务器L实例评测|docker 常用操作命令
    二分练习题
  • 原文地址:https://blog.csdn.net/ruanlinxi1994/article/details/125482883