基本语法
usiing 关键字
using 关键字用于在程序中包含命名空间。一个程序可以包含多个 using 语句
class关键字
class 关键字用于声明一个类。
注释
单行注释
多行注释
成员变量
变量是类的属性或数据成员,用于存储数据。
成员函数
也可以叫做成员方法
函数是一系列执行指定任务的语句。类的成员函数是在类内声明的。
类的实例化
只要理解 “类是模板,对象是实例” ,就能掌握实例化的核心思想。
这个过程使用
new
关键字调用类的构造函数来完成。
代码演示:
ClassName instanceName = new ClassName(参数列表);
完整代码演示:
using System;// 1. 定义一个类
public class Person
{// 字段(可选)private string name;private int age;// 属性(推荐使用属性封装字段)public string Name{get { return name; }set { name = value; }}public int Age{get { return age; }set { age = value >= 0 ? value : 0; } // 简单验证}// 无参构造函数public Person(){Name = "未知";Age = 0;}// 有参构造函数public Person(string name, int age){Name = name;Age = age;}// 方法public void Introduce(){Console.WriteLine($"大家好,我叫 {Name},今年 {Age} 岁。");}
}// 2. 主程序:实例化类
class Program
{static void Main(string[] args){// 实例化方式 1:使用无参构造函数Person person1 = new Person();person1.Name = "张三";person1.Age = 25;person1.Introduce(); // 输出:大家好,我叫 张三,今年 25 岁。// 实例化方式 2:使用有参构造函数Person person2 = new Person("李四", 30);person2.Introduce(); // 输出:大家好,我叫 李四,今年 30 岁。// 实例化方式 3:C# 9.0+ 支持 target-typed new 表达式(更简洁)Person person3 = new("王五", 22);person3.Introduce(); // 输出:大家好,我叫 王五,今年 22 岁。// 每个实例都是独立的对象Console.WriteLine($"person1 和 person2 是同一个对象吗?{ReferenceEquals(person1, person2)}"); // False}
}
标识符
标识符是用来识别类、变量、函数或任何其它用户定义的项目
在 C# 中,类的命名必须遵循如下基本规则:
- 标识符必须以字母、下划线或
@ 开头
,后面可以跟一系列的字母、数字( 0 - 9 )、下划线( _ )、@。 - 标识符中的第一个字符不能是数字。
- 标识符必须不包含任何嵌入的空格或符号,比如
? - +! # % \^ & \* ( ) [ ] { } . ; : " ' / \\。
- 标识符不能是 C# 关键字。除非它们有一个 @ 前缀。 例如,@if 是有效的标识符,但 if 不是,因为 if 是关键字。
- 标识符必须区分大小写。大写字母和小写字母被认为是不同的字母。
- 不能与C#的类库名称相同。
CSharp 关键字
关键字是 C# 编译器预定义的保留字。这些关键字不能用作标识符,但是,如果您想使用这些关键字作为标识符,可以在关键字前面加上 @ 字符作为前缀。
作用:
它们是语言的“保留词”,用于定义结构、控制流程、管理内存、实现面向对象和高级功能,不能用作标识符(如变量名)。
在 C# 中,有些关键字在代码的上下文中有特殊的意义,如 get 和 set,这些被称为上下文关键字(contextual keywords)。
顶级语句(Top-Level Statements)
这是C# 9 版本中引入的顶级语句 ,是一种新的编程范式
允许开发者在文件的顶层直接编写语句,而不需要将它们封装在方法或类中。
特点:
- 无需类或方法:顶级语句允许你直接在文件的顶层编写代码,无需定义类或方法。
- 文件作为入口点:包含顶级语句的文件被视为程序的入口点,类似于 C# 之前的
Main
方法。 - 自动
Main
方法:编译器会自动生成一个Main
方法,并将顶级语句作为Main
方法的主体。 - 支持局部函数:尽管不需要定义类,但顶级语句的文件中仍然可以定义局部函数。
- 更好的可读性:对于简单的脚本或工具,顶级语句提供了更好的可读性和简洁性。
- 适用于小型项目:顶级语句非常适合小型项目或脚本,可以快速编写和运行代码。
- 与现有代码兼容:顶级语句可以与现有的 C# 代码库一起使用,不会影响现有代码。
传统代码演示:
using System;namespace MyApp
{class Program{static void Main(string[] args){Console.WriteLine("Hello, World!");}}
}
顶级语句代码演示:
using System;Console.WriteLine("Hello, World!");
顶级语句支持所有常见的 C# 语法,包括声明变量、定义方法、处理异常等。
using System;
using System.Linq;// 顶级语句中的变量声明
int number = 42;
string message = "The answer to life, the universe, and everything is";// 输出变量
Console.WriteLine($"{message} {number}.");// 定义和调用方法
int Add(int a, int b) => a + b;
Console.WriteLine($"Sum of 1 and 2 is {Add(1, 2)}.");// 使用 LINQ
var numbers = new[] { 1, 2, 3, 4, 5 };
var evens = numbers.Where(n => n % 2 == 0).ToArray();
Console.WriteLine("Even numbers: " + string.Join(", ", evens));// 异常处理
try
{int zero = 0;int result = number / zero;
}
catch (DivideByZeroException ex)
{Console.WriteLine("Error: " + ex.Message);
}
注意事项
- 文件限制: 顶级语句只能在一个源文件中使用。如果在一个项目中有多个使用顶级语句的文件,会导致编译错误。
- 程序入口: 如果使用顶级语句,则该文件会隐式地包含 Main 方法,并且该文件将成为程序的入口点。
- 作用域限制: 顶级语句中的代码共享一个全局作用域,这意味着可以在顶级语句中定义的变量和方法可以在整个文件中访问。
简单理解:
顶级语句在简化代码结构、降低学习难度和加快开发速度方面具有显著优势,特别适合于编写简单程序和脚本。
数据类型
在 C#
中,变量分为以下几种类型:
- 值类型(Value types)
- 引用类型(Reference types)
- 指针类型(Pointer types)
值类型
值类型变量可以直接分配给一个值。它们是从类 System.ValueType 中派生的。
值类型直接包含数据。比如 int、char、float,它们分别存储数字、字符、浮点数。当您声明一个 int 类型时,系统分配内存来存储值。
如需得到一个类型或一个变量在特定平台上的准确尺寸,可以使用 sizeof 方法
表达式 sizeof(type) 产生以字节为单位存储对象或类型的存储尺寸。
代码演示:
using System;namespace DataTypeApplication
{class Program{static void Main(string[] args){Console.WriteLine("Size of int: {0}", sizeof(int));Console.ReadLine();}}
}
用来读取多少个字节的
C# 中的值类型直接包含数据,赋值和传参时复制整个值,典型代表包括所有基本类型(int
、bool
等)、struct
和 enum
。
引用类型
引用类型不包含存储在变量中的实际数据,但它们包含对变量的引用。
换句话说,它们指的是一个内存位置。使用多个变量时,引用类型可以指向一个内存位置。
如果内存位置的数据是由一个变量改变的,其他变量会自动反映这种值的变化。
内置的 引用类型有:object、dynamic 和 string。
引用类型就像“快递单”——变量里存的不是东西本身,而是东西的“地址”。多个快递单可以指向同一个包裹,谁改了包裹内容,大家看到的都一样。
对象类型:
当一个值类型转换为对象类型时,则被称为 装箱;另一方面,当一个对象类型转换为值类型时,则被称为 拆箱。
指针类型
但是我目前来说好像并没有怎么去使用过
指针类型变量存储另一种类型的内存地址。C# 中的指针与 C 或 C++ 中的指针有相同的功能。
声明指针类型的语法:
type* identifier;
例如:
char* cptr;
int* iptr;
类型转换
类型转换的概念:在 C# 中,类型转换是将一个数据类型的值转换为另一个数据类型的过程。
C# 中的类型转换可以分为两种:隐式类型转换和显式类型转换(也称为强制类型转换)。
隐士类型转换
隐式转换是不需要编写代码来指定的转换,编译器会自动进行。
像是很平稳的过度 ,小转大
隐式转换是指将一个较小范围的数据类型转换为较大范围的数据类型时,编译器会自动完成类型转换,这些转换是 C# 默认的以安全方式进行的转换, 不会导致数据丢失。
例如,从 int 到 long,从 float 到 double 等。
从小的整数类型转换为大的整数类型,从派生类转换为基类。将一个 byte 类型的变量赋值给 int 类型的变量,编译器会自动将 byte 类型转换为 int 类型,不需要显示转换。
代码演示:
byte b = 10;
int i = b; // 隐式转换,不需要显式转换
将一个整数赋值给一个长整数,或者将一个浮点数赋值给一个双精度浮点数,这种转换不会导致数据丢失:
int intValue = 42;
long longValue = intValue; // 隐式转换,从 int 到 long
显示类型转换
显式类型转换,即 强制类型转换 ,需要程序员在代码中明确指定。
显式转换是指将一个较大范围的数据类型转换为较小范围的数据类型时,或者将一个对象类型转换为另一个对象类型时,需要使用强制类型转换符号进行显示转换,强制转换会造成数据丢失。
例如,将一个 int 类型的变量赋值给 byte 类型的变量,需要显示转换。
int i = 10;
byte b = (byte)i; // 显式转换,需要使用强制类型转换符号
强制转换为整数类型:
但是这样转换的话避免不了的会造成精度丢失的
double doubleValue = 3.14;
int intValue = (int)doubleValue; // 强制从 double 到 int,数据可能损失小数部分
C# 类型转换方法
C# 提供了下列内置的类型转换方法:(我感觉还挺好用的)
序号 | 方法 & 描述 |
---|---|
1 | ToBoolean 如果可能的话,把类型转换为布尔型。 |
2 | ToByte 把类型转换为字节类型。 |
3 | ToChar 如果可能的话,把类型转换为单个 Unicode 字符类型。 |
4 | ToDateTime 把类型(整数或字符串类型)转换为 日期-时间 结构。 |
5 | ToDecimal 把浮点型或整数类型转换为十进制类型。 |
6 | ToDouble 把类型转换为双精度浮点型。 |
7 | ToInt16 把类型转换为 16 位整数类型。 |
8 | ToInt32 把类型转换为 32 位整数类型。 |
9 | ToInt64 把类型转换为 64 位整数类型。 |
10 | ToSbyte 把类型转换为有符号字节类型。 |
11 | ToSingle 把类型转换为小浮点数类型。 |
12 | ToString 把类型转换为字符串类型。 |
13 | ToType 把类型转换为指定类型。 |
14 | ToUInt16 把类型转换为 16 位无符号整数类型。 |
15 | ToUInt32 把类型转换为 32 位无符号整数类型。 |
16 | ToUInt64 把类型转换为 64 位无符号整数类型。 |
这些方法都定义在 System.Convert 类中,使用时需要包含 System 命名空间
它们提供了一种安全的方式来执行类型转换,因为它们可以处理 null值,并且会抛出异常,如果转换不可能进行。这里可以处理null 我觉得就很重要
代码演示:使用 Convert.ToInt32 方法将字符串转换为整数:
这样的使用我其实觉得和Java中的调用各种API是差不多的 ,使用的时候也很方便
string str = "123";
int number = Convert.ToInt32(str); // 转换成功,number为123
不过如果字符串不是有效的整数表示,Convert.ToInt32 将抛出 FormatException。
代码演示:
using System;namespace TypeConversionApplication
{class StringConversion{static void Main(string[] args){// 定义一个整型变量int i = 75;// 定义一个浮点型变量float f = 53.005f;// 定义一个双精度浮点型变量double d = 2345.7652;// 定义一个布尔型变量bool b = true;// 将整型变量转换为字符串并输出Console.WriteLine(i.ToString());// 将浮点型变量转换为字符串并输出Console.WriteLine(f.ToString());// 将双精度浮点型变量转换为字符串并输出Console.WriteLine(d.ToString());// 将布尔型变量转换为字符串并输出Console.WriteLine(b.ToString());// 等待用户按键后关闭控制台窗口Console.ReadKey();}}
}
在进行类型转换时需要注意以下几点:
- 隐式转换只能将 较小范围的数据类型转换为较大范围的数据类型 ,不能 将较大范围的数据类型转换为较小范围的数据类型 ;
- 显式转换可能会导致数据丢失或精度降低,需要进行数据类型的兼容性检查;
- 对于对象类型的转换,需要进行类型转换的兼容性检查和类型转换的安全性检查。
类型转换方法
C# 提供了多种类型转换方法,例如使用 Convert 类、Parse 方法和 TryParse 方法,这些方法可以帮助处理不同的数据类型之间的转换。
这三个在日常使用中 ,我用的还是比较多的 ,也是需要必须掌握的知识
使用 Convert类
Convert 类提供了一组静态方法,可以在各种基本数据类型之间进行转换。
代码演示:
string str = "123";
int num = Convert.ToInt32(str);
使用 Pars方法
作用:Parse 方法用于将字符串转换为对应的数值类型,如果转换失败会抛出异常。
代码演示:
string str = "123.45";
double d = double.Parse(str);
使用 TryParse方法
TryParse 方法类似于 Parse,但它不会抛出异常,而是返回一个布尔值指示转换是否成功。
代码演示:
string str = "123.45";
double d;
bool success = double.TryParse(str, out d);if (success) {Console.WriteLine("转换成功: " + d);
} else {Console.WriteLine("转换失败");
}
自定义类型转换
C# 还允许你定义自定义类型转换操作,通过在类型中定义 implicit 或 explicit 关键字。
不过这个我好像并没有怎么接触过 ,也算是我的一个知识盲区吧
代码演示:
using System;public class Fahrenheit
{public double Degrees { get; set; }public Fahrenheit(double degrees){Degrees = degrees;}// 隐式转换从Fahrenheit到doublepublic static implicit operator double(Fahrenheit f){return f.Degrees;}// 显式转换从double到Fahrenheitpublic static explicit operator Fahrenheit(double d){return new Fahrenheit(d);}
}public class Program
{public static void Main(){Fahrenheit f = new Fahrenheit(98.6);Console.WriteLine("Fahrenheit object: " + f.Degrees + " degrees");double temp = f; // 隐式转换Console.WriteLine("After implicit conversion to double: " + temp + " degrees");Fahrenheit newF = (Fahrenheit)temp; // 显式转换Console.WriteLine("After explicit conversion back to Fahrenheit: " + newF.Degrees + " degrees");}
}
总结:
在 C# 中,内置的类型转换方法主要通过以下几种方式实现:隐式转换、显式转换(强制转换)、使用 Convert 类的方法、Parse 方法和 TryParse 方法,这些方法广泛应用于不同数据类型之间的转换。
变量
一个变量只不过是一个供程序操作的存储区的名字。
在 C# 中,变量是用于存储和表示数据的标识符,在声明变量时,您需要指定变量的类型,并且可以选择性地为其分配一个初始值。
就像这个样子:int number_a = 10; 或者 int number_b;
在 C# 中,每个变量都有一个特定的类型,类型决定了变量的内存大小和布局,范围内的值可以存储在内存中,可以对变量进行一系列操作。
C# 中提供的基本的值类型大致可以分为以下几类:
类型 | 举例 |
---|---|
整数类型 | sbyte、byte、short、ushort、int、uint、long、ulong 和 char |
浮点型 | float, double |
十进制类型 | decimal |
布尔类型 | true 或 false 值,指定的值 |
空字符串 | string |
空类型 | 可为空值的数据类型 |
C# 允许定义其他值类型的变量 , 比如 enum,也允许定义引用类型变量,比如 class。
变量的定义
代码演示:
int i, j, k;
char c, ch;
float f, salary;
double d;
变量的初始化
int i = 100;
变量的命名规则
在 C# 中,变量的命名需要遵循一些规则:
- 变量名可以包含字母、数字和下划线。
- 变量名必须以字母或下划线开头。
- 变量名区分大小写。
- 避免使用 C# 的关键字作为变量名。
代码演示:
int myVariable = 10;
string _userName = "John";
C# 中的变量初始化
变量通过在等号后跟一个常量表达式进行初始化(赋值)。初始化的一般形式为:
int d = 3, f = 5; /* 初始化 d 和 f. */
byte z = 22; /* 初始化 z. */
double pi = 3.14159; /* 声明 pi 的近似值 */
char x = 'x'; /* 变量 x 的值为 'x' */
变量可以在声明时被初始化(指定一个初始值)。初始化由一个等号后跟一个常量表达式组成
接收来自用户的值
System 命名空间中的 Console 类提供了一个函数 ReadLine() ,用于接收来自用户的输入,并把它存储到一个变量中。
代码演示:
int num;
num = Convert.ToInt32(Console.ReadLine());
函数 Convert.ToInt32() 把用户输入的数据转换为 int 数据类型,因为 Console.ReadLine() 只接受字符串格式的数据。
C# 中的 Lvalues 和 Rvalues
C# 中的两种表达式:
- lvalue:lvalue 表达式可以出现在赋值语句的左边或右边。
- rvalue:rvalue 表达式可以出现在赋值语句的右边,不能出现在赋值语句的左边
变量是 lvalue 的,所以可以出现在赋值语句的左边。数值是 rvalue 的,因此不能被赋值,不能出现在赋值语句的左边。
代码演示:
// 可行的
int g = 20
// 不可行的
10 = 20 // 像这种方式肯定是不可以的
变量作用域
在 C# 中,变量的作用域定义了变量的可见性和生命周期。
变量的作用域通常由花括号{ }
定义的代码块来确定。
变量作用域的规则:
局部变量
在方法、循环、条件语句等代码块内声明的变量是局部变量,它们只在声明它们的代码块中可见。
代码演示:
void MyMethod()
{int localVar = 10; // 局部变量// ...
}
// localVar 在这里不可见
块级作用域
说明:在 C# 7及更高版本中,引入了块级作用域,即使用大括号 {} 创建的任何块都可以定义变量的作用域。
代码演示:
{int blockVar = 20; // 块级作用域// ...
}
// blockVar 在这里不可见
方法参数作用域
方法的参数也有其自己的作用域,它们在整个方法中都是可见的。
代码演示:
void MyMethod(int parameter)
{// parameter 在整个方法中可见// ...
}
全局变量
在类的成员级别定义的变量是成员变量,它们在整个类中可见
如果在命名空间级别定义,那么它们在整个命名空间中可见。
代码演示:
class MyClass
{int memberVar = 30; // 成员变量,在整个类中可见
}
静态变量作用域
静态变量是在类级别上声明的,但它们的作用域也受限于其定义的类。
调用的时候也非常的方便可以直接这样子去做:类名.变量名
代码演示:
class MyClass
{static int staticVar = 40; // 静态变量,在整个类中可见
}
循环变量作用域
在 for 循环中声明的循环变量在循环体内可见
这个用的还是比较多的 ,只不过我自己平常并没有过多的去注意罢了!
代码演示:
for (int i = 0; i < 5; i++)
{// i 在循环体内可见
}
// i 在这里不可见
总体而言,变量的作用域有助于管理变量的可见性和生命周期,确保变量在其有效范围内使用,也有助于防止命名冲突。
常量
常来是固定的 ,执行期间不会改变
常量可以是任何基本数据类型,比如整数常量、浮点常量、字符常量或者字符串常量,还有枚举常量。
常量可以被当作常规的变量,只是它们的值在定义后不能被修改。
整数常量
整数常量可以是十进制、八进制或十六进制的常量。
前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,没有前缀则表示十进制。
整数常量也可以有后缀,可以是 U 和 L 的组合,其中,U 和 L 分别表示 unsigned 和 long。后缀可以是大写或者小写,多个后缀以任意顺序进行组合。
这个刚开始我还没看懂 ,一看到后缀名瞬间就清晰明了了
一些整数常量的实例:
212 /* 合法 */
215u /* 合法 */
0xFeeL /* 合法 */
078 /* 非法:8 不是一个八进制数字 */
032UU /* 非法:不能重复后缀 */
以下是各种类型的整数常量的实例:
85 /* 十进制 */
0213 /* 八进制 */
0x4b /* 十六进制 */
30 /* int */
30u /* 无符号 int */
30l /* long */
30ul /* 无符号 long */
浮点常量
一个浮点常量是由整数部分、小数点、小数部分和指数部分组成
您可以使用小数形式或者指数形式来表示浮点常量。
这里有一些浮点常量的实例:
3.14159 /* 合法 */
314159E-5L /* 合法 */
510E /* 非法:不完全指数 */
210f /* 非法:没有小数或指数 */
.e55 /* 非法:缺少整数或小数 */
使用浮点形式表示时,必须包含小数点、指数或同时包含两者
使用指数形式表示时,必须包含整数部分、小数部分或同时包含两者。
有符号的指数是用 e 或 E 表示的。
字符常量
字符常量是括在单引号里,例如,'x'
,且可存储在一个简单的字符类型变量中。
一个字符常量可以是一个普通字符(例如 'x')、 一个转义序列(例如 '\t')或者一个通用字符(例如 '\u02C0')。 , 这里的话我感觉我是有点看不懂的 ,难搞啊
在 C# 中有一些特定的字符,当它们的前面带有反斜杠时有特殊的意义,可用于表示换行符(\n)或制表符 tab(\t)
转义序列 | 含义 |
---|---|
\|\ 字符 | |
\' | ' 字符 |
\" | " 字符 |
\? | ? 字符 |
\a | Alert 或 bell |
\b | 退格键(Backspace) |
\f | 换页符(Form feed) |
\n | 换行符(Newline) |
\r | 回车 |
\t | 水平制表符 tab |
\v | 垂直制表符 tab |
\ooo | 一到三位的八进制数 |
\xhh . . . | 一个或多个数字的十六进制数 |
以下是一些转义序列字符的实例:
namespace EscapeChar
{class Program{static void Main(string[] args){Console.WriteLine("Hello\tWorld\n\n");Console.ReadLine();}}
}
感觉有点像制表符
字符串常量
字符串常量是括在双引号 " "
里,或者是括在 @" "
里。
字符串常量包含的字符与字符常量相似,可以是:普通字符、转义序列和通用字符
使用字符串常量时,可以把一个很长的行拆成多个行,可以使用空格分隔各个部分。
代码演示:
string a = "hello, world"; // hello, world
string b = @"hello, world"; // hello, world
string c = "hello \t world"; // hello world
string d = @"hello \t world"; // hello \t world
string e = "Joe said \"Hello\" to me"; // Joe said "Hello" to me
string f = @"Joe said ""Hello"" to me"; // Joe said "Hello" to me
string g = "\\\\server\\share\\file.txt"; // \\server\share\file.txt
string h = @"\\server\share\file.txt"; // \\server\share\file.txt
string i = "one\r\ntwo\r\nthree";
string j = @"one
two
three";
但是我感觉这样的用法并不是很多
定义常量
常量使用的是const
关键字来定义的 ,语法就是:
const 变量类型 变量名 = 值; // 差不多是这个样子
正统的:
const <data_type> <constant_name> = value;
代码演示:
using System;public class ConstTest
{class SampleClass{public int x;public int y;public const int c1 = 5;public const int c2 = c1 + 5;public SampleClass(int p1, int p2) {x = p1; y = p2;}}static void Main(){SampleClass mC = new SampleClass(11, 22);Console.WriteLine("x = {0}, y = {1}", mC.x, mC.y);Console.WriteLine("c1 = {0}, c2 = {1}", SampleClass.c1, SampleClass.c2);}
}
运算符
运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C# 有丰富的内置运算符,分类如下:
- 算术运算符
- 关系运算符
- 逻辑运算符
- 位运算符
- 赋值运算符
- 其他运算符
大致有:算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符及其他运算符。
算术运算符
大致有:加减乘除 ,取余 ,自增运算符 ,自减运算符
关系运算符
下表显示了 C# 支持的所有关系运算符。假设变量 A 的值为 10,变量 B 的值为 20,则:
运算符 | 描述 | 实例 |
---|---|---|
== | 检查两个操作数的值是否相等,如果相等则条件为真。 | (A == B) 不为真。 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真。 | (A != B) 为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 | (A > B) 不为真。 |
< | 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 | (A < B) 为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 | (A >= B) 不为真。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 | (A <= B) 为真。 |
代码演示:
using System;class Program
{static void Main(string[] args){int a = 21;int b = 10;if (a == b){Console.WriteLine("Line 1 - a 等于 b");}else{Console.WriteLine("Line 1 - a 不等于 b");}if (a < b){Console.WriteLine("Line 2 - a 小于 b");}else{Console.WriteLine("Line 2 - a 不小于 b");}if (a > b){Console.WriteLine("Line 3 - a 大于 b");}else{Console.WriteLine("Line 3 - a 不大于 b");}/* 改变 a 和 b 的值 */a = 5;b = 20;if (a <= b){Console.WriteLine("Line 4 - a 小于或等于 b");}if (b >= a){Console.WriteLine("Line 5 - b 大于或等于 a");}}
}
逻辑运算符
下表显示了 C# 支持的所有逻辑运算符。假设变量 A 为布尔值 true,变量 B 为布尔值 false,则:
运算符 | 描述 | 实例 |
---|---|---|
&& | 称为逻辑与运算符。如果两个操作数都非零,则条件为真。 | (A && B) 为假。 |
|| | 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。 | (A || B) 为真。 |
! | 称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。 | !(A && B) 为真。 |
这个我最近做项目的时候就使用到了这个逻辑运算符了
代码演示:
using System;namespace OperatorsAppl
{class Program{static void Main(string[] args){bool a = true;bool b = true;if (a && b){Console.WriteLine("Line 1 - 条件为真");}if (a || b){Console.WriteLine("Line 2 - 条件为真");}/* 改变 a 和 b 的值 */a = false;b = true;if (a && b){Console.WriteLine("Line 3 - 条件为真");}else{Console.WriteLine("Line 3 - 条件不为真");}if (!(a && b)){Console.WriteLine("Line 4 - 条件为真");}Console.ReadLine();}}
}
位运算符
位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示:
var result = 忘记了 ,反正返回的类型是一个布尔类型的
result &= 后面的逻辑
// 我觉得这样子设计的挺好的
p | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
假设如果 A = 60,且 B = 13,现在以二进制格式表示,它们如下所示:
A = 0011 1100
B = 0000 1101
A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~A = 1100 0011
下表列出了 C# 支持的位运算符。假设变量 A 的值为 60,变量 B 的值为 13,则:
运算符 | 描述 | 实例 |
---|---|---|
& | 如果同时存在于两个操作数中,二进制 AND 运算符复制一位到结果中。 | (A & B) 将得到 12,即为 0000 1100 |
| | 如果存在于任一操作数中,二进制 OR 运算符复制一位到结果中。 | (A | B) 将得到 61,即为 0011 1101 |
^ | 如果存在于其中一个操作数中但不同时存在于两个操作数中,二进制异或运算符复制一位到结果中。 | (A ^ B) 将得到 49,即为 0011 0001 |
~ | 按位取反运算符是一元运算符,具有"翻转"位效果,即0变成1,1变成0,包括符号位。 | (~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。 |
<< | 二进制左移运算符。左操作数的值向左移动右操作数指定的位数。 | A << 2 将得到 240,即为 1111 0000 |
>> | 二进制右移运算符。左操作数的值向右移动右操作数指定的位数。 | A >> 2 将得到 15,即为 0000 1111 |
我怎么感觉我有点听不懂呢
代码演示:
using System;
namespace OperatorsAppl
{class Program{static void Main(string[] args){int a = 60; /* 60 = 0011 1100 */ int b = 13; /* 13 = 0000 1101 */int c = 0; c = a & b; /* 12 = 0000 1100 */ Console.WriteLine("Line 1 - c 的值是 {0}", c );c = a | b; /* 61 = 0011 1101 */Console.WriteLine("Line 2 - c 的值是 {0}", c);c = a ^ b; /* 49 = 0011 0001 */Console.WriteLine("Line 3 - c 的值是 {0}", c);c = ~a; /*-61 = 1100 0011 */Console.WriteLine("Line 4 - c 的值是 {0}", c);c = a << 2; /* 240 = 1111 0000 */Console.WriteLine("Line 5 - c 的值是 {0}", c);c = a >> 2; /* 15 = 0000 1111 */Console.WriteLine("Line 6 - c 的值是 {0}", c);Console.ReadLine();}}
}
结果演示:
Line 1 - c 的值是 12
Line 2 - c 的值是 61
Line 3 - c 的值是 49
Line 4 - c 的值是 -61
Line 5 - c 的值是 240
Line 6 - c 的值是 15
赋值运算符
下表列出了 C# 支持的赋值运算符:
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符,把右边操作数的值赋给左边操作数 | C = A + B 将把 A + B 的值赋给 C |
+= | 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 | C += A 相当于 C = C + A |
-= | 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 | C -= A 相当于 C = C - A |
*= | 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 | C *= A 相当于 C = C * A |
/= | 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 | C /= A 相当于 C = C / A |
%= | 求模且赋值运算符,求两个操作数的模赋值给左边操作数 | C %= A 相当于 C = C % A |
<<= | 左移且赋值运算符 | C <<= 2 等同于 C = C << 2 |
>>= | 右移且赋值运算符 | C >>= 2 等同于 C = C >> 2 |
&= | 按位与且赋值运算符 | C &= 2 等同于 C = C & 2 |
^= | 按位异或且赋值运算符 | C ^= 2 等同于 C = C ^ 2 |
|= | 按位或且赋值运算符 | C |= 2 等同于 C = C | 2 |
代码演示:
using System;namespace OperatorsAppl
{class Program{static void Main(string[] args){int a = 21;int c;c = a;Console.WriteLine("Line 1 - = c 的值 = {0}", c);c += a;Console.WriteLine("Line 2 - += c 的值 = {0}", c);c -= a;Console.WriteLine("Line 3 - -= c 的值 = {0}", c);c *= a;Console.WriteLine("Line 4 - *= c 的值 = {0}", c);c /= a;Console.WriteLine("Line 5 - /= c 的值 = {0}", c);c = 200;c %= a;Console.WriteLine("Line 6 - %= c 的值 = {0}", c);c <<= 2;Console.WriteLine("Line 7 - <<= c 的值 = {0}", c);c >>= 2;Console.WriteLine("Line 8 - >>= c 的值 = {0}", c);c &= 2;Console.WriteLine("Line 9 - &= c 的值 = {0}", c);c ^= 2;Console.WriteLine("Line 10 - ^= c 的值 = {0}", c);c |= 2;Console.WriteLine("Line 11 - |= c 的值 = {0}", c);Console.ReadLine();}}
}
其他运算符
下表列出了 C# 支持的其他一些重要的运算符,包括 sizeof、typeof 和 ? : 。
运算符 | 描述 | 实例 |
---|---|---|
sizeof() | 返回数据类型的大小。 | sizeof(int),将返回 4. |
typeof() | 返回 class 的类型。 | typeof(StreamReader); |
& | 返回变量的地址。 | &a; 将得到变量的实际地址。 |
* | 变量的指针。 | *a; 将指向一个变量。 |
? : | 条件表达式 | 如果条件为真 ? 则为 X : 否则为 Y |
is | 判断对象是否为某一类型。 | If( Ford is Car) // 检查 Ford 是否是 Car 类的一个对象。 |
as | 强制转换,即使转换失败也不会抛出异常。 | Object obj = new StringReader("Hello"); StringReader r = obj as StringReader; |
这几个用的还是比较多的 ,无论是sizeof()
还是typerof
以及is
和 as
typeof 关键字用于获取一个类型的类型对象,它通常用于反射和动态创建类型实例。
运算符的优先级
运算符的优先级确定表达式中顶的组合
这会影响到一个表达式如何计算。某些运算符比其他运算符有更高的优先级
例如,乘除运算符具有比加减运算符更高的优先级。
这个感觉还是需要靠自己多多的感悟下的
注意: 由于括号可以改变运算符优先级,所以在实际应用中建议尽可能使用括号来明确运算顺序,提高代码的可读性和准确性。