1.3C#语言的运算符(Operator)和表达式(Expression)

1.一元运算符

运算符描述
+x一元 + 运算符返回其操作数的值。
-x一元 - 运算符对其操作数的数值取负。
++x++x 的结果是按 1 递增其操作数后的 x 的值。
--x--x 的结果是按 1 递减其操作数后的 x 的值。
x++x++ 的结果是按 1 递增其操作数前的 x 的值。
x--x-- 的结果是按 1 递减其操作数前的 x 的值。

2.算术运算符

运算符描述
x + y加法、字符串连接、委托实例组合
x - y减法、委托实例移除
x * y乘法
x / y除法
x % y余数

3.赋值运算符

运算符描述
x = y赋值
x += y加法赋值、订阅事件、字符串连接赋值
x -= y减法赋值、取消订阅事件
x *= y乘法赋值
x /= y除法赋值
x %= y余数赋值
x &= y逻辑与赋值、位逻辑与赋值
x |= y逻辑或赋值、位逻辑或赋值
x ^= y逻辑异或赋值、位逻辑异或赋值
x <<= y左移位赋值
x >>= y右移位赋值
=>lambda 表达式(匿名函数),Expression-bodied表达式
= ref引用分配给ref局部变量 或 ref readonly局部变量

4.相等运算符

运算符名称描述
x == y相等如果操作数相等,等于运算符 == 返回 true,否则返回 false
x != y不等如果操作数不相等,不等于运算符 != 返回 true,否则返回 false。 

5.比较运算符

运算符名称描述
x < y小于如果左侧操作数小于右侧操作数,< 运算符返回 true,否则返回 false
x > y大于如果左侧操作数大于右侧操作数,> 运算符返回 true,否则返回 false
x <= y小于或等于如果左侧操作数小于或等于右侧操作数,<= 运算符返回 true,否则返回 false
x >= y大于或等于如果左侧操作数大于或等于右侧操作数,>= 运算符返回 true,否则返回 false

6.布尔逻辑运算符

& 运算符与 && 运算符的区别是:如果左侧操作数的计算结果为 false&& 运算符则不会计算右侧操作数。而 & 运算符 无论左侧操作数的计算结果是 truefalse,都会计算右侧操作数。因此, && 运算符 的性能比 & 运算符 高。x | y 运算符与 x || y 运算符的区别类似。

运算符名称描述
!x逻辑非如果 x 的计算结果为 false,则 !x 的结果为 true,否则,结果为 false
x & y逻辑与如果 x 和 y 的计算结果都为 true,则 x & y 的结果为 true,否则,结果为 false
x | y逻辑或如果 x 或 y 的计算结果为 true,则 x | y 的结果为 true。 否则,结果为 false
x ^ y逻辑异或如果 x 的计算结果为 true 且 y 的计算结果为 false,或者 x 的计算结果为 false 且 y 的计算结果为 true,那么 x ^ y 的结果为 true。 否则,结果为 false。 
x && y条件逻辑与(又称“短路逻辑与”)x & y,但不支持Nullable类型的操作数。
x || y条件逻辑或(又称”短路逻辑或”)x | y,但不支持Nullable类型的操作数。
andand运算符x & y。例如,>= 3 and < 6 => "spring"
oror运算符x | y。例如,12 or (>= 1 and < 3) => "winter"

布尔逻辑运算符一览表:

xyx&yx|yx^y!x
truetruetruetrueflasefalse
truefalsefalsetruetruefalse
truenullnulltruenullfalse
falsetruefalsetruetruetrue
falsefalsefalsefalsefalsetrue
falsenullfalsenullnulltrue
nulltruenulltruenullnull
nullfalsefalsenullnullnull
nullnullnullnullnullnull

7.三元条件运算符

运算符描述
x ? y : z如果 x 为 true,则计算 y;如果 x 为 false,则计算 z

8.按位和移位运算符

运算符名称描述
~x按位求补~ 运算符通过反转每个位产生其操作数的按位求补。也可以使用 ~ 符号来声明终结器。
x & y位逻辑与& 运算符计算其整型操作数的位逻辑 与。
x | y位逻辑或| 运算符计算其整型操作数的位逻辑 或。
x ^ y位逻辑异或^ 运算符计算其整型操作数的位逻辑 异或。
x << y向左移位<< 运算符将其左侧操作数向左移动右侧操作数定义的位数。
x >> y向右移位>> 运算符将其左侧操作数向右移动右侧操作数定义的位数。

9.类型测试运算符和强制转换表达式

运算符名称描述
typeof(T)typeof运算符typeof 运算符用于获取某个类型的 System.Type 实例。typeof 运算符的实参必须是类型或类型形参的名称,不可以是表达式。
nameof(T)nameof表达式nameof 表达式可生成变量、类型或成员的字符串常量名称。例如,Console.WriteLine(nameof(System.Collections.Generic)); // output: Generic
sizeof(T)sizeof运算符sizeof 运算符返回给定类型的变量所占用的字节数。
E is TE is T ais 表达式如果 E 表达式的类型与 T 类型兼容,则返回 true 并将 E 表达式的值赋值给变量 a;否则,返回 false
E is not T is not 表达式如果 E 表达式的类型与 T 类型不兼容,则返回 true ;否则,返回 false。 比如:result is not nullinput is not (float or double)
E is { P: value1,F:value2 }属性模式比如:static bool IsConferenceDay(DateTime date) => date is { Year: 2020, Month: 5, Day: 19 or 20 or 21 };
E as Tas 运算符如果 E 表达式能转换为 T 类型,则返回 类型为 T 的 E,否则返回 null。等同于E is T ? (T)(E) : (T)nullas 运算符仅考虑引用类型、Nullable、装箱和取消装箱转换,不能使用 as 运算符执行用户定义的转换,为此,请使用强制转换表达式。
(T)E强制转换表达式(cast expression)形式为 (T)E 的强制转换表达式将表达式 E 的结果显式转换为类型 T

10.成员访问运算符和表达式

运算符名称描述
a.x成员访问表达式用于访问命名空间或类型的成员。
f(x)调用表达式使用括号 () 调用方法或调用委托。还可以使用括号来调整表达式中计算操作的顺序。
a[i]数组元素或索引器运算符方括号 [] 通常用于数组、索引器或指针元素访问,还用于指定特性。
^n从末尾开始索引运算符对于长度为 length 的序列,^n 指向与序列开头偏移 length - n 的元素。例如,^1 指向序列的最后一个元素,^length 指向序列的第一个元素。
x..y范围运算符左侧操作数是范围的包含性开头,右侧操作数是范围的不包含性末尾。

11.Null运算符

运算符名称描述
a?.xNull条件运算符如果 a 为非 null,则 a?.x 的结果将与 a.x 的结果相同。否则,将返回 null
a?[i]Null条件运算符如果 a 为非 null,则 a?[i] 的结果将与 a[x] 的结果相同。否则,将返回 null
x ?? yNull合并运算符如果 xnull,则返回值为 y ,否则返回 x
x ??= yNull合并赋值运算符如果 xnull,则将 y 赋值给 x ,否则不赋值。
x!Null包容运算符(又称”Null抑制运算符“)通过使用 Null包容运算符,可以告知编译器传递 null 是预期行为,不应发出警告。

12.指针运算符

运算符名称描述
&xaddress-of运算符用于获取固定变量(驻留在不受垃圾回收器操作影响的存储位置的变量)的地址,可移动变量(驻留在受垃圾回收器影响的存储位置的变量)需使用fixed语句固定获取地址。&运算符无法获取常量或值的地址。
*x指针间接运算符(又称”取消引用运算符“)用于获取指针指向的变量,* 运算符的操作数必须是指针类型。
x->y指针成员访问运算符-> 运算符是指针间接运算符和成员访问表达式的合并,等同于(*x).y
p[n]指针元素访问运算符对于指针类型的表达式 pp[n] 形式的指针元素访问计算方式为 *(p + n),其中 n 必须是可隐式转换为 intuintlong 或 ulong 的类型。
p + n向指针增加整数值p + n 和 n + p 表达式都生成 T* 类型的指针,该指针是将 n * sizeof(T) 添加到 p 给出的地址得到的。
p - n从指针中减少整数值p - n 表达式生成 T* 类型的指针,该指针是从 p 给出的地址中减去 n * sizeof(T) 得到的。
p1 - p2指针减法运算符对于类型为 T* 的两个指针 p1 和 p2p1 - p2 计算公式为 ((long)(p1) - (long)(p2)) / sizeof(T)
++x指针递增前缀同一元运算符。
--x指针递减前缀同一元运算符。
x++指针递增后缀同一元运算符。
x--指针递减后缀同一元运算符。
==指针相等同相等运算符。
!=指针不等同相等运算符。
<指针小于同比较运算符。
>指针大于同比较运算符。
<=指针小于或等于同比较运算符。
>=指针大于或等于同比较运算符。

13.默认值表达式

运算符名称描述
default(T)default运算符default 运算符的实参必须是类型或类型形参的名称,例如:Console.WriteLine(default(int)); // output: 0
defaultdefault字面值可以使用 default 文本生成类型的默认值,例如:T initialValue = default
default:default标签可以将 default 关键字用作 switch 语句中的默认用例标签。

14.::(命名空间运算符)

运算符描述
::使用命名空间别名限定符 :: 访问已设置别名的命名空间的成员。:: 限定符左侧标识符必须是命名空间别名。
global::global 关键字与 :: 限定符表示全局命名空间别名。

15.new运算符

通用类类型描述
new T();使用 构造函数 创建类或委托的对象。
new();如果已知表达式的类型,则可以省略类型名称。
new T() {...};使用 构造函数对象初始值设定项 创建对象。
new() {...};如果已知表达式的类型,则可以省略类型名称并使用 构造函数对象初始值设定项 创建对象。
new T {...};不使用 构造函数,使用 对象初始值设定项 创建对象。
匿名类型描述
new {...};只使用 对象初始值设定项 创建匿名类型的对象。
数组类型描述
new T[n];声明类型为T,长度为n的数组。
new T[n] {...};声明类型为T,长度为n的数组,并使用数组初始值设定项初始化。
new T[] {...};声明类型为T的数组,并使用数组初始值设定项初始化,长度由初始化推断确定。
new[] {...};只使用数组初始值设定项声明并初始化数组,类型和长度由初始化推断确定。

16.stackalloc表达式

stackalloc 是单词stack(堆栈)和单词allocate(分配)的合并简写,表示在堆栈上分配内存块。

//T必须是非托管类型
//E的计算结果必须为非负int值
stackalloc T[E];

16.1分配给Span<T>或ReadOnlySpan<T>

stackalloc 表达式的结果分配给 Span<T>或 ReadOnlySpan<T> 变量时,不必使用 unsafe 上下文。

建议尽可能使用 Span<T> 或 ReadOnlySpan<T> 类型来处理堆栈中分配的内存。

int length = 3;
Span<int> numbers = stackalloc int[length];
for (var i = 0; i < length; i++)
{
    numbers[i] = i;
}
//使用数组初始值设定项语法来定义新分配内存的内容
Span<int> first = stackalloc int[3] { 1, 2, 3 };
Span<int> second = stackalloc int[] { 1, 2, 3 };
ReadOnlySpan<int> third = stackalloc[] { 1, 2, 3 };

16.2分配给指针类型

stackalloc 表达式的结果分配给 指针 变量时,必须使用 unsafe 上下文。

unsafe
{
    int length = 3;
    int* numbers = stackalloc int[length];
    for (var i = 0; i < length; i++)
    {
        numbers[i] = i;
    }
}

17.switch表达式

可以使用 switch 表达式,将与 方法形参兼容 的 输入表达式 与 => 运算符左侧的候选表达式进行比较,从而返回第一个匹配的候选表达式右侧的表达式的值。

注意:switch 表达式虽与选择语句里的 switch 语句提供类似的功能,但是两回事。

候选表达式可以是整数、浮点、布尔、字符、字符串、枚举、const常量、null、类型名称、弃元变量、比较表达式、属性表达式等等。

候选表达式可能表现力不够,无法详细描述switch  arm计算的条件。在这种情况下,可以附加 case guard,必须与候选表达式同时满足。可以在候选表达式后面的 when 关键字之后指定一个 case guard,case guard 必须是布尔表达式。

返回类型 方法名(形参) => 输入表达式 switch
{
    候选表达式1 => 表达式1,
    候选表达式2 => 表达式2,
    候选表达式3 [when 布尔表达式3] => 表达式3,
    候选表达式N [when 布尔表达式N] => 表达式N,
}

18.true和false运算符

true 运算符返回 bool 值 true,以指明其操作数一定为 true。 false 运算符返回 bool 值 true,以指明其操作数一定为 false

如果某类型定义这两个运算符之一,那它还必须定义另一个运算符。

public static bool operator true(LaunchStatus x) => x == Green || x == Yellow;
public static bool operator false(LaunchStatus x) => x == Red;

19.with表达式

with 表达式使用修改的特定属性和字段与左侧操作数的副本生成新的对象。

with 表达式的左侧操作数可以是记录类型或匿名类型。

var p2 = p1 with { Name = "B", X = 5 };

原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/csharp/csharplang/7863.html

(0)
上一篇 2021年1月3日 02:56
下一篇 2021年1月4日 00:01

相关推荐

  • 1.6C#语言的选择(Selection)、迭代(Iteration)、跳转(Jump)语句

    1.if选择 2.if-else选择 3.if-else-if-else选择 4.switch选择 default case 指定匹配表达式与其他任何 case 模式都不匹配时要执行的语句。 通常在每个 switch section末尾使用 break 语句将控制从 switch…

    C#语言教程 2021年1月6日
    02800
  • 2.8C#函数成员之运算符(Operator)

    运算符声明 所有运算符都必须声明为 public 和 static。 隐式和显式运算符 implicit 或 explicit 关键字分别用于定义隐式转换或显式转换,定义转换的类型必须是该转换的源类型或目标类型,可用两种类型中的任何一种类型来定义两种用户定义类…

    C#语言教程 2021年2月8日
    0800
  • 2.1C#语言的变量(Variable)

    1.变量声明和初始化 2.变量分类 x 是一个静态变量, y 它是一个实例变量,a 是一个值参数,b 是一个引用参数,c 是一个输出参数,v[0] 是一个数组元素,i 是一个局部变量。 2.1成员变量 名称 修饰符 静态变量 用 static 修饰 实例变量 无 static 修饰 2.2…

    C#语言教程 2021年2月1日
    02750

发表评论

登录后才能评论