【C#本质论 四】操作符和控制流程

标签: C#本质论  操作符和控制流程  操作符优先级  预编译指令

本篇博客延续前三篇的写作方式,因为内容较为基础,只是以冷热知识的形式列出旧有的容易忽视的C#特性及新出现的特性,当然对一些之前较为模糊的概念也予以整理。

概念重现

1,操作符的概念,操作符分为一元、二元、三元三大类,分别对应一、二、三个操作数,分别包含如下的逻辑:

  • 一元正负操作符,表示数值的正负
  • 二元算术操作符,包括+,-,*,/,%等。
  • 三元条件操作符,包括?:两个操作符隔着三个操作数

2,代码块、作用域和声明空间的区别:声明空间是具名事物的逻辑容器,代码块是两个大括号之间的多条语句,而作用域表示声明的具名事物的作用范围。作用域决定一个名称引用什么事物,而声明空间决定同名的两个事物是否冲突

3,switch语句使用的时候有如下规范

  • switch 语句中的 expression 必须是一个整型或枚举类型,或者是一个 class 类型,其中 class 有一个单一的转换函数将其转换为整型或枚举类型。
  • 在一个 switch 中可以有任意数量的 case 语句。每个 case 后跟一个要比较的值和一个冒号。
  • case 的 constant-expression 必须与 switch 中的变量具有相同的数据类型,且必须是一个常量。
  • 当被测试的变量等于 case 中的常量时,case 后跟的语句将被执行,直到遇到 break 语句为止。当遇到 break 语句时,switch 终止,控制流将跳转到 switch 语句后的下一行。
  • 不是每一个 case 都需要包含 break。如果 case 语句为空,则可以不包含 break,控制流将会 继续 后续的 case,直到遇到 break 为止
  • C# 不允许从一个开关部分继续执行到下一个开关部分。如果 case 语句中有处理语句,则必须包含 break 或其他跳转语句,否则会编译失败
  • 一个 switch 语句可以有一个可选的 default case,出现在 switch 的结尾。default case 可用于在上面所有 case 都不为真时执行一个任务。default case 中的 break 语句不是必需的。
  • C# 不支持从一个 case 标签显式贯穿到另一个 case 标签。如果要使 C# 支持从一个 case 标签显式贯穿到另一个 case 标签,可以使用 goto 一个 switch-case 或 goto default

4,C#的预编译指令,和常量以及常量表达式一样,C#预编译指令在编译时调用:
在这里插入图片描述

使用的时候一般是用#define定义一个值,然后依据定义来编译代码:

#define PI
using System;
namespace PreprocessorDAppl
{
   class Program
   {
      static void Main(string[] args)
      {
         #if (PI)
            Console.WriteLine("PI is defined");
         #else
            Console.WriteLine("PI is not defined");
         #endif
         Console.ReadKey();
      }
   }
}

输出为:

PI is defined

可以用if debug来确定调试时运行哪些代码:

   public static void Main(string[] fileName)
        {
#if DEBUG
            System.Console.WriteLine("只有debug时候使用");
#endif
        }

C#冷知识

1,在C#中,只有赋值、调用、递增、递减、 await(用于异步编程) 和对象创建表达式才能作为独立语句使用。

2,再来梳理一遍操作符优先级吧!从上到下可以按照如下方式归类:

  • 主要运算符:有++、–、()、+、-、!、~。这一级中都是单元运算符,除了其中那一对特殊的具有改变任何运算优先级的括号。这此可以看出,在定义表达式中,那些单元运算符的优先级是很高的,可能是因为它们都直接作用于操作数吧。
  • 算术运算符:在常规算术运算符中,有我们经常使用的*、/、%、+、-,因为他们使用得较多,所以也排在较高的位置。这一级是两个特殊的位操作符,<< 和 >>,它们是所有二元操作符中除常规运算符外优先级最高的了,可能是因为与比较运算符、逻辑运算符比起来,这一组操作符进行的还是数值的计算。
  • 比较运算符:包括<、>、<=、>=、==、!=,一共六个,这里有一个特点,就小于优先于大于。
  • 逻辑运算符,逻辑运算符原本有四种,但用于单元的“非”运算符排在了前面,所以这里面就只有&、^、|,再加上两个补充的用于提高代码效率的运算符&&、||等共有五个。
  • 赋值运算符,这一级最多,几乎前面出现过的二元运算符,在这里加上个“=”号就成为一个赋值运算符。首先当然最基本的赋值运算符“=”;然后是常规算术运算符演变来的“*=、/=、%=、+=、-=”,它们的顺序和常规算术符的顺序一样;然后是位移运算符和逻辑运算符,也按它们演变前的顺序排列,为“<<=、>>=、&=、^=、|=”。因为比较运算符所产生的结果的数据类型和它的运算数的数据类型不同,所以它们没有相应的赋值运算符。

在这里插入图片描述

3,C#的大多数操作符是左结合的,而赋值操作符是右结合的

4,在算术运算符中使用字符:先把字符转为数值,得到数值后再转为字符

       public static void Main()
        {
            int n = '3' + '4';
            char c = (char)n;
            System.Console.WriteLine(c);  //g
        }

5,结合性和优先级,结合性决定相似操作符的执行顺序,优先级决定不相似操作符的执行顺序,而操作数总是从左向右求值操作符的结合性和优先级只影响操作符自身的执行顺序,不影响操作数的求值顺序

6,C#禁止一个代码块中声明的局部变量在其子代码块中重复声明

7,&&和||是短路运算符,只要左边第一个表达式满足条件,就不会继续对右边求值

8,事先知道循环次数使用for循环,事先不知道使用while

9,goto语句可以使用lable的方式执行:

myLabel: System.Console.WriteLine("if条件要求为bool类型哦");
goto myLabel;

但是需要注意的是,goto只能跳转到自己上级代码块和同级代码块,不能跳到自己的子代码块,而且要避免使用goto语句。

C#新知识

1,var temp=++count是先给count自增再赋值,var temp=count++是先给temp赋值再自增count,需要注意的是,这个操作不是原子操作,是线程不安全的

2,空合并操作符:如果fileName为null,就使用tml,也就是如果这个值为null,就使用另一个。

      public static void Main()
        {
            string fileName = null;
            string fullName = fileName ?? "tml";
        }

3,空条件操作符:调用成员前先进行空检查,需要注意,int类型的话返回的是int?,数值类型都类似。

     public static void Main(string[] fileName)
        {
            var length = fileName?.Length;
        }

需要注意的是,if条件操作符要求的条件必须为bool类型,所以要结合空合并操作符使用

 public static void Main(string[] fileName)
        {
            if (fileName[0]?.StartsWith("") ?? false)
            {
                System.Console.WriteLine("if条件要求为bool类型哦");
            }
        }

4,foreach用于循环遍历数据项集合的每一项,保证不发生越界错误!foreach循环期间,禁止修改循环变量(数据项)以及数据集合

版权声明:本文为sinat_33087001原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sinat_33087001/article/details/103376158

智能推荐

C# 操作符 ?? 和 ?:

原文链接:https://msdn.microsoft.com/zh-cn/library/ms173224(v=vs.80).aspx 如果 ?? 运算符的左操作数非空,该运算符将返回左操作数,否则返回右操作数。 备注 可空类型可以包含值,或者可以是未定义的。 ?? 运算符定义:当可空类型分配给非可空类型时返回的默认值。如果在将可空类型分配给非可空类型时不使用 ?? 运算符,将生成编译时错误。如...

C#中的空接合操作符(??)和null条件操作符(?.)

空接合操作符(null coalescing operator) ?? 能简单地表示“如果这个值为空,就使用另一个值”。 其形式如下:expression1 ?? expression2 ??操作符支持短路求值。如果expression1不为null, 就返回expression1的值, 不对另一个表达式求值。如果expression1求值null,就返回expressio...

C#——操作符

操作符概览 优先级从上到下递减, 同级从左到右,添加“()”改变优先级, 带有赋值功能的运算符从右到左 操作符的本质 操作符的本质时函数(即算法)的“简记法” 简化函数 操作符不能脱离与他相关联的数据类型 操作符可以看作固定数据类型之间的“简记法” 操作符应用实例...

C语言(四) 操作符和表达式(上)

操作符 分类: 算术操作符 +  -  *  /  % 1. 除了%操作符之外,其他的几个操作符可以作用于整数和浮点数。 2. 对于/操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就 是浮点数除法。 3. %操作符的两个操作数必须为整数。返回的是整除之后的余数。 移位操作符 << 左移操作符 >> 右移操作符 左移操...

【C】操作符

    C具有丰富的操作符,它提供了所有你希望编程语言应该拥有的操作符,而且,C的许多操作符具有其他语言的操作符无可抗衡的价值,这正是C适用于开发范围极广的应用程序的原因之一。     C中有很多复杂的表达式,假如表达式中的操作符超过一个,那么是什么决定这些操作符的执行顺序呢?我们知道,C的每个操作符都具有优先级,用于确定它和表达式中其余...

猜你喜欢

C++第40课--前置操作符++重载和后置操作符++重载

本文学习自 狄泰软件学院 唐佐林老师的 C++课程 实验1:++i 和 i++ 真的不一样吗 实验2:++操作符的重载 根据C的前后置++的语义, 前置++ 返回 变量自加后本身, 后置++ 先保存自己的值到一个临时变量,然后再自加1,最后返回保存的临时变量。那么在C++中 前置++ 返回对象自加后本身,后置++返回 对象自加前的值,不返回自加后本身。所以前置++重载返回的是 Test& ...

C++学习笔记 第40课 前置操作符和后置操作符

值得思考的问题 在编译器中反汇编可知,i++和++i的汇编代码是一样的 问题产生的原因: 现代编译器会对代码进行优化 优化会使二进制代码更加高效 优化后的二进制程序丢失C/C++的原生语义 不可能从编译后的二进制程序还原C/C++程序 ++操作符重载 全局函数和成员函数都可以被重载 重载前置++操作符不需要额外的参数 重载后置++操作符需要一个int类型的占位参数 真正的区别 小结 1.编译优化使...

冒泡排序,及改进方式,性能优化400%>>>附图解加源码

首先源码附上,源码中带有注释,看不懂没关系,源码后面附带图解,最后附上代码效率提升图 源码如下: 方案一:其实实现很简单,两层循环,每次内层迭代出最大的一个值,将其放入数组最后一个位置,外层循环的末端便往前移一位。其原理如下图 方案一代码块: 方案二:优化改进 仔细观察上面的图,我们不难发现当迭代到图下这样的情况时,其实已经全排序好了,但是我们还是需要对它进行1,2,3,4,5,6的迭代,这些情况...

css3常用选择器

先介绍一下基本选择器,如下几种 *:通配符。选择页面的所有元素 E:元素选择器。对页面的一些元素进行选择,如p,div,li等 .class:类选择器 #id:id选择器。一个Id在一个页面中只能选择,这是和类选择器的区别 E F:后代选择器。如ul li。选中ul下的li E>F:子元素选择器。如下,可以用 h1 > strong {color:red;}使h1的子元素strong变...

python is not set from command line or npm configuration

问题 猜测原因  python版本冲突 解决方案  去官网找到最新版本python 点击下载,注意记住你下载的目录,下载好以后,打开这个目录下的文件夹,Python310, 整个文件夹复制一下 在项目里运行npm config list --json 找到python的路径   我的是 C:\\Python27\\python.exe 说明项目里用的还是py...