类别 | 运算符 |
---|---|
基本 | 成员访问运算符: x.y ;方法调用操作符: f(x) ;元素访问操作符: a[x] ; 后置自增: x++ ; 后置自减: x-- ; 创建类型的实例: new ; 查看类型的内部结构: typeof ; 获取类型的默认值: default ;检查数据是否有溢出: checked ; 不检查数据是否有溢出: unchecked ;声明匿名方法: delegate ; 获取基本数据类型对象所占内存大小: sizeof ; 指针访问对象成员 : -> ; |
一元 | 正值: + ; 负值: - ; 取非: ! ; 按位求反: ~ ; 前置自增: ++x ; 前置自减: --x ; 强制类型转换: (T) x ; 用于异步操作时:await ; 取地址: &x ; 解引用: *x ; |
乘除法 | 乘法: * ; 除法: / ;求余: % ; |
加减法 | 加法: + ; 减法: - ; |
位移 | 向左移位: << ; 向右移位: >> ; |
关系和类型检测 | 小于: < ;大于: > ;小于等于: <= ;大于等于: >=;检查对象是否兼容: is ;进行类型转换: as ; |
相等 | 等于: == ; 不等于: != ; |
逻辑“与” | & |
逻辑“异或” | ^ |
逻辑“或” | l |
条件“与 ” | && |
条件“或 ” | ll |
null 合并 | ?? |
条件 | ?:: |
赋值和Lambda表达式 | = ;*=; /= ; %= ;+=; -=; <<= ;>>= ;&= ;^=; l= ; Lambda表达式: =>; |
运算优先级从上到下依次递减,“基本”最高,“赋值”最低,同一级别的优先级为从左到右,
“赋值”类的运算符优先级为从右到左
一、操作符的重载
public static 返回类型 operator +(传入的参数)
{
方法体;
}
//定义一个类,用于表示三维坐标
class Vector
{
public double x, y, z;
public Vector(double x,double y,double z)
{
this.x = x;
this.y = y;
this.z = z;
}
public Vector (Vector rhs)
{
x = rhs.x;
y = rhs.y;
z = rhs.z;
}
//重写ToString()方法
public override string ToString()
{
return "(" + x + "," + y + "," + z + ")";
}
//重写加号运算符
public static Vector operator + (Vector lhs,Vector rhs)
{
Vector result = new Vector(lhs);
result.x += rhs.x;
result.y += rhs.y;
result.z += rhs.z;
return result;
}
}
二、基本运算符
1、成员访问运算符 .
成员访问运算符作用:1、外层名称空间的子集名称空间(名称空间可以嵌套名称空间的)。2、名称空间中的类型。3、类型中的静态成员。4、对象的成员。
//System.IO 名称空间 File 类 类型 Create 静态方法
System.IO.File.Create("D:\\a.txt");
//声明了一个对象myForm
Form myForm = new Form();
//访问myForm的 Text 属性
myForm.Text = "a";
// 调用myForm中的ShowDialog()方法
myForm.ShowDialog();
2、方法调用操作符 ()
f(x): f:方法的名称。 x:方法的参数。
3、元素访问操作符 []
元素访问操作符主要用于访问数组中的元素和词典中的元素。
//声明一个int型的数组,并确定了数组的长度
int[] myArray = new int[4];
//声明一个int型的数组,确定了数组的长度并给每个元素赋值
int[] myArray1 =new int[4] { 4, 5, 6, 8 };
//声明一个int型的数组,让编译器推算数组的长度
int[] myArray2 = new int[] { 4, 5, 6, 8 };
//简化的写法,声明并初始化数组
int[] myArray3 = { 4, 5, 6, 8 };
//使用下标来访问数组的值,数组下标从0开始,数组最大下标为(myArray3.Length-1)
//把数组myArray2中的6替换为8
myArray2[2]=myArray3[myArray3.Length - 1];
static void Main(string[] args)
{
//声明了一个字典类型的变量,键为string类型的值,值唯一,不能有重复,值为Student的类
Dictionary<string, Student> stuDic = new Dictionary<string, Student>();
Student a = new Student();
a.Name = "a1";
a.Score = 10;
stuDic.Add(a.Name, a);
//使用键值来访问集合中的元素
Student b = stuDic["a1"];
Console.WriteLine(b.Score);
}
class Student
{
public string Name;
public int Score;
}
4、创建类型的实例并调用实例的构造器初始化实例 new
new操作符的主要功能是在内存当中创建类型的实例并且立刻调用它的实例构造器,如果new操作符它的左边有赋值操作符(=)的话就把它拿到的实例内存地址通过赋值操作交给负责访问实例的变量。
Form a = new Form();
//在()后加上{}后,就可以调用实例的初始化器,可以在大括号里给实例的属性赋值
Form b = new Form(){Text = "你好!" };
5、typeof 和 default的用法
查看类型的内部结构: typeof
获取类型的默认值: default
Type t = typeof(int);
//获取int的名称空间
Console.WriteLine(t.Namespace);
//获取int的类型全名
Console.WriteLine(t.FullName);
//获取int的不带名称空间的名字
Console.WriteLine(t.Name);
//获得int的所有公共方法的集合
t.GetMethods();
//var 推断类型
var x = 100;
// 获取x变量的类型名称
x.GetType().Name;
//获取int类型的默认值
int a = default(int);
6、typeof 和 default的用法
检查数据是否有溢出: checked
不检查数据是否有溢出: unchecked(默认不检查)
//声明一个16位的整数对象x并且给x赋值一个16位数可以存储的最大数
uint x = uint.MaxValue;
//输出这个数
Console.WriteLine(x);
//输出这个数的二进制形式
Console.WriteLine(Convert.ToString(x, 2));
//可能抛出异常的代码
try
{
//发生溢出后抛出溢出异常
uint y = checked(x + 1);
//发生溢出后不抛出溢出异常
uint z = unchecked(x + 1);
Console.WriteLine(y);
}
//捕获异常后进行处理
catch
{
Console.WriteLine("发生了数据溢出");
}
//检查程序块中是否有溢出,发生溢出后抛出异常
checked
{
}
//不检查程序块中是否有溢出
unchecked
{
}
7、delegate的用法
delegate的用法:1、用来声明匿名方法(已经不建议使用,声明匿名方法建议使用 Lambda表达式: =>) 。2、用来声明委托。
//使用delegate创建匿名方法
//该匿名方法为按钮的Click事件
this.MyButton.Click += delegate (object sender, EventArgs e)
{
this.MyTextBox.Text = "你好";
};
//使用 Lambda表达式创建匿名方法
this.MyButton.Click += ( sender, e) =>
{
this.MyTextBox.Text = "你好";
};
//委托的声明
//委托的定义 委托一般定义在名称空间下
public delegate 方法的返回值类型 委托的类型名称(方法的参数列表);
//定义了一个返回值类型为double类型 参数为两个double类型的委托
public delegate double Calc(double x, double y);
//委托的使用
class Program
{
static void Main(string[] args)
{
//创建一个实例
Calculator calculator = new Calculator();
//把实例的方法交给委托
Calc calc1 = new Calc(calculator.Add);
Calc calc2 = new Calc(calculator.Sub);
Calc calc3 = new Calc(calculator.Mul);
double a = 200;
double b = 100;
double c = 0;
//通过委托来访问calculator的加法
c = calc1.Invoke(a, b);
//也可以通过()方式来调用
c = calc1(a, b);
//输出 300
Console.WriteLine(c);
c = calc2.Invoke(a, b);
//输出 100
Console.WriteLine(c);
c = calc3.Invoke(a, b);
//输出 20000
Console.WriteLine(c);
}
}
class Calculator
{
public double Add(double x, double y)
{
return x + y;
}
public double Sub(double x, double y)
{
return x - y;
}
public double Mul(double x, double y)
{
return x * y;
}
}
8、sizeof的用法
//int类型在内存中占4个字节
int x = sizeof(int);
//long类型在内存中占8个字节
int x = sizeof(long );
//double类型在内存中占8个字节
int x = sizeof(double);
//decimal类型在内存中占16个字节
int x = sizeof(decimal);
//不安全的代码要放进 unsafe 中,还要在项目的属性中勾选允许不安全的代码
unsafe
{
//计算结构体类型的大小
int x = sizeof(Student);
//输出16
Console.WriteLine(x);
}
//声明一个结构体
struct Student
{
int ID;
long Score;
}
9、指针成员访问符 -> 的用法
在C#中指针操作只能用在结构体类型,不能用在操作引用类型。
//不安全的代码要放进 unsafe 中,还要在项目的属性中勾选允许不安全的代码
unsafe
{
//声明结构体类型变量
Student stu;
//给结构体属性赋值
stu.ID = 1;
stu.Score = 50;
//声明一个指针变量并且取stu变量的地址赋给 指针变量
Student* pStu = &stu;
//通过指针来访问结构体的属性值
pStu->Score = 60;
//输出60 通过.直接访问
Console.WriteLine(stu.Score);
//通过解引用操作符来访问结构体的属性值
//因为成员访问操作符.的优先级高于解引用操作符*,所以要加()改变优先级
(*pStu).Score = 80;
//输出80 通过.直接访问
Console.WriteLine(stu.Score);
//输出1 通过指针间接访问
Console.WriteLine(pStu->ID);
}
//声明一个结构体
struct Student
{
public int ID;
public long Score;
}
三、一元操作符(单目操作符)
1、取非: !
布尔类型,取非为 true 变成 false ; false 变成 true
2、按位求反: ~
按位求反为 0变1 、1变0
C#中求相反数操作为按位求反并加1。
int x =12345678;
int y = ~x;
//ToString(x, 2)把数值以二进制显示 PadLeft(32, '0') 显示32位,不足以0补齐
string xStr = Convert.ToString(x, 2).PadLeft(32, '0');
string yStr = Convert.ToString(y, 2).PadLeft(32, '0');
//显示为 00000000101111000110000101001110
Console.WriteLine(xStr);
//显示为 11111111010000111001111010110001
Console.WriteLine(yStr);
3、类型转换
1、隐式类型转换分为 不丢失精度的转换、子类向父类的转换和装箱。
static void Main(string[] args)
{
//不丢失精度的转换
//int表示的最大数
int x =int.MaxValue;
//发生了隐式类型转换
long y = x;
//子类向父类进行转换
//创建一个子类类型
Teacher t = new Teacher();
//把子类类型转换成了父类类型
//发生了隐式类型转换,h只能访问 Human 类里有的方法,不能访问子类的方法
Human h = t;
//发生了隐式类型转换
Animal a = h;
//装箱
//装箱是将值类型转换为 object 类型或由此值类型实现的任何接口类型的过程
//值类型转成object类型
object o1 = x;
//Teacher子类 类型转成object类型
object o = t;
//拆箱
//object类型转成值类型
//发生了强制类型转换
int z = (int)o1;
//object类型转成Teacher子类 类型
//发生了强制类型转换
Teacher b = (Teacher)o;
}
class Animal
{
public void Eat()
{
Console.WriteLine("");
}
}
class Human:Animal
{
public void Think()
{
Console.WriteLine("");
}
}
class Teacher:Human
{
public void Teach()
{
Console.WriteLine("");
}
}
2、显示类型转换分为 有可能丢失精度(甚至发生错误)的转换、拆箱、使用Convert类、ToString方法和各数据类型的Parse/TryParse方法。
//丢失精度的转换
long x =int.MaxValue;
//发生了显式类型转换
int y = (int)x;
//使用Convert类
//把long类型的数据转换成int类型的数据
int z = Convert.ToInt32(x);
//把数值类型转换成字符串
//使用ToString()方法
//将long 类型的数据转换成字符串
string str = x.ToString();
str = Convert.ToString(x);
//把字符串转换成数值
long lo = Convert.ToInt64(str);
//Parse方法将字符串转换成数值
//如果字符串格不是数值类型就会抛出异常
lo = long.Parse(str);
//TryParse方法将字符串转换成数值
//TryParse方法返回值为bool类型 参数要求两个,一个是要转换的字符串,一个是输出参数
//如果字符串格不是数值类型不会抛出异常,返回值为false
bool b = long.TryParse(str, out lo);
3、自定义类型转换操作符。
1、声明显式类型转换操作符,关键字 explicit
public static explicit operator 要转换的类型(当前类型 stone)
{
要转换的类型 m = new 要转换的类型();
return m;
}
public static explicit operator Monkey(Stone stone)
{
Monkey m = new Monkey();
m.Age = stone.Age;
return m;
}
2、声明隐式类型转换操作符,关键字 implicit
public static implicit operator 要转换的类型(当前类型 stone)
{
要转换的类型 m = new 要转换的类型();
return m;
}
public static implicit operator Monkey(Stone stone)
{
Monkey m = new Monkey();
m.Age = stone.Age;
return m;
}
class Program
{
static void Main(string[] args)
{
Stone stone = new Stone();
//显示类型转换
Monkey monkey = (Monkey)stone;
}
}
//要把Stone类转换成 Monkey类 就在Stone类中添加类型转换操作符
class Stone
{
public int Age;
//声明一个显示类型转换
public static explicit operator Monkey(Stone stone)
{
Monkey m = new Monkey();
m.Age = stone.Age;
return m;
}
}
class Monkey
{
public int Age;
}
四、移位
1、向左移位: <<
向左移位: << 时未发生溢出时,位移一位相当于乘以2 。
2、向右移位: >>
向右移位: >> 时未发生溢出时,位移一位相当于除以2 。
五、类型检测
1、is运算符可以检查对象是否与特定的类型兼容
is关键字是用于检查对象是否与给定类型兼容,如果兼容就返回true,如果不兼容就返回false。
//is 的使用
bool b = 对象名 is 类型名 ;
2、as运算符用于执行引用类型的显式类型转换
as关键字会直接进行类型转换,如果转换成功会返回转换后的对象,如果转换不成功则不会抛出异常而是返回null
//as 的使用
类型名 b = 对象名 as 类型名 ;
if( b !=null)
{
Console.WriteLine("转换成功");
}
六、关系运算符
1、关系运算符
关系运算符的得到的结果为布尔类型 bool 值为 true 或 false
比较运算符:== 等于; != 不等于; < 小于 ; > 大于 ; <= 小于等于; >=大于等于;
2、条件运算符
条件运算符用来操作布尔类型的数据
条件运算符: &&与 ; || 或 ; ! 逻辑非(结果取反)。
&&与:b1 && b2 ;只有b1和b2 都为true时,结果为true。
|| 或:b1 || b2 ;b1和b2 有一个为true时,结果为true。
! 逻辑非:! b1 ;b1为true时,结果为false;b1为false时,结果为true。
3、三元运算符
三元运算符: 表达式 ? 结果1:结果2 ; 如果表达式成立,整个表达式的结果为 结果1,否则为 结果2 .
七、逻辑(位)运算符
操作数据的二进制结构。
逻辑运算符:& 逻辑与(安位与); | 逻辑或(按位或); ^ 逻辑异或(按位异或); ~ 按位求反 ;
八、算术运算符
算术运算符:+ 加法 - 减法 * 乘法 / 除法 % 求余
九、null 合并
//声明了一个int可空类型的变量x
int? x = null;
//输出结果为false HasValue判断x是否有值
Console.WriteLine(x.HasValue);
//如果x为null 就用20替代
int y = x??20;
//输出结果为20
Console.WriteLine(y);