操作符
操作符 表达式 语句…皆是为方法服务
操作符造作数构成表达式 表达式后面加;构成语句 ,语句s组成方法体 构成算法逻辑
- 概览
操作符(Operator) 也叫运算符
操作符用来操作数据 被操作符操作的数据叫操作数(Operand)
类别|运算符
—|—
基本|x.y
一元
乘法
加法
移位
关系和类型检测
逻辑”与“
逻辑”或“
逻辑”非“
。。。。
图
-
本质
- 函数的”简记法“ 简化算法
- 操作符不能脱离与它相关联的数据类型
- 操作符就是与固定数据类型相关联的一套基本算法的简记法
- 为自定义数据类型创建操作符
int x=5; int y=4; int z=x/y; Console.WriteLine(z);//输出1 double a=5.0; double b=4.0; double c=x/y; Console.WriteLine(c);//输出1.25
-
优先级
- 可以通过()提高表达式优先级
- ()可以嵌套
-
同级运算顺序
-
除了带有赋值功能的操作符,同优先级的操作符都是从左向右进行运算
-
带有赋值功能的操作符运算顺序都是从右向左
int x=100; int y=200; int z=300; x+=y+=z; Console.WriteLine(x);//600 Console.WriteLine(y);//500 Console.WriteLine(z);//300
-
与数学运算不同,计算机语言的同优先级运算没有结合律
- 3+4+5只能理解为Add(Add(3,4),5)
- 不能理解为Add(3,Add(4,5))
基本操作符
-
- “.” 示例
class Program
{
public static void Main(string[] args)
{
Calculator c=new Calculator();
Action myAction=new Action(c.PrintHello);
myAction();
}
}
class Calculator
{
public double Add(double a,double b)
{
return a+b;
}
public void PrintHello()
{
Console.WriteLine("Hello");
}
}
-
"[]"示例
- 访问数组
class Program { public static void Main(string[] args) { int[] myintArray=new int[10]; //int[] myintArray=new int[]{1,2,3,4,5};//{}初始化器 Console.WriteLine(myintArray[0]);//访问数组第一个元素 Console.WriteLine(myintArray[myintArray.length-1]);//访问数组最后一个元素 }
- 访问字典 "[]"放对集合元素的索引
class Program { public static void Main(string[] args) { Dictionary<string,Student> stuDic=new Dictionary<string,Student>; for(int i=1, i<=100,i++) { Student stu=new Student(); stu.Name="s_"+i.ToString(); stu.Score=100+i; stuDic.Add(stu.Name,stu); } Student number6=stuDic["s_6"]; Console.WriteLine(number6.Score); } } class Student{ public string Name; public int Score; }
-
”++“
class Program { public static void Main(string[] args) { int x=100; x++;//x=x+1; Console.WriteLine(x);//101 } }
-
”–“
class Program { public static void Main(string[] args) { int x=100; x--;//x=x-1; Console.WriteLine(x);//99 } }
class Program { public static void Main(string[] args) { int x=100; int y=x++;//相当于 //int y=x; x=x+1; Console.WriteLine(x);// 101 Console.WriteLine(y);// 100 } }
class Program { public static void Main(string[] args) { int x=100; int y=x--;//相当于 //int y=x; x=x-1; Console.WriteLine(x);// 99 Console.WriteLine(y);// 100 } }
-
”typeof”操作符
class Program { public static void Main(string[] args) { //MataData Type t=typeof(int); Console.WriteLine(t.NameSpace);//System Console.WriteLine(t.FullName);//System.Int32 Console.WriteLine(t.Name);//Int32 int c=t.GetMethods().Length; foreach(var mi in t.GetMethods()) { Console.WriteLine(mi.Name); } Console.WriteLine(c); } }
-
“default”
- 结构体类型
class Program { public static void Main(string[] args) { int x = default(int); double y=default(double); Console.WriteLine(x);//0 Console.WriteLine(y);//0 } }
- 枚举
class Program { public static void Main(string[] args) { Level level=default(Level); Console.WriteLine(level);//low } } enum Level {//默认情况 Low,//0 Mid,//1 High//2 //手动规定 //Low=1, //Mid=0, //默认值为Mid //High=2 } //使用枚举的时候最好手动设置值为0的值,如果不设置的话 默认值只会返回0 不会返回枚举值
- 引用
class Program { public static void Main(string[] args) { Form myForm= new Form(); Console.WriteLine(myForm==null);//True } }
-
new 操作符
在内存中创建一个类型的实例 并且立刻调用这个类型的实例构造器
var x 一个隐式类型的变量
int x: 一个显式类型的变量
- 调用实例的构造器
class Program { public static void Main(string[] args) { Form myForm=new Form();//new操作符还能得到实例的地址把实例的地址通过赋值符号“=”交给访问实实例的变量myForm 由此构成变量和实例间的引用关系 myForm.Text="Hello";//通过变量访问实例 myForm.ShowDialog(); } }
- 调用实例的初始化器
class Program { public static void Main(string[] args) { //new Form().ShowDialog(); //new Form(){Text="Hello"}.ShowDialog(); Form myForm=new Form(){Text="Hello"}; myForm.ShowDialog(); } }
- 只要想在内存中创建类型的实例,就要去调用new操作符? 答案不是
class Program { public static void Main(string[] args) { string name="Tim";//C#语法糖衣 int x=100; int [] myArray={1,2,3,4}//int[] myArray=new int[10]; } }
- new操作符创建匿名对象
///为匿名类型创建对象 用隐式类型变量引用实例 class Program { public static void Main(string[] args) { Form myForm=new Form(){Text="Hello"};//非匿名类型 var person=new{Name="Mr.Okay",Age=35};//声明一个隐式类型 Console.WriteLine(person.Name);//Mr.Okay Console.WriteLine(person.Age);//35 Console.WriteLine(person.GetType().Name);//<>f_AnonyousType0^2 0创建的第一个 ^2 需要两个类型构成这个泛型类 } }
!!!不要随意使用new操作符 ,一旦在某个类里调用了new操作符 正在编写的类型就和创建实例的类型构成了紧密的耦合关系 开发应遵循高内聚,低耦合的特点,通过依赖注入解决
- new的其他用法 作为修饰符而不作为操作符
class Program
{ public static void Main(string[] args)
{
Student stu=new Student();
stu.Report();
CsStudent csStu=new CsStudent();
csStu.Report();
}
}
class Student
{
public void Report()
{
Console.WriteLine("I'm a student");
}
}
class CsStudent:Student
{
new public void Report() //new作为修饰符
{
Console.WriteLine("I'm CS student");//子类对父类的方法进行了隐藏
}
}
}
-
checked/unchecked - 检查一个值是否在内存中有溢出
- 操作符用法
class Program{ public static void Main(string[] args) { uint x = uint.MaxValue; Console.WriteLine(x); string binStr=Convert.ToString(x,2); Console.WriteLine(binStr); //uint y = x + 1 ; //Console.WriteLine(y);// 0 所有位进位 最后一位丢掉 //======================================== //uint y = checked(x + 1); //Console.WriteLine(y);//overflow //======================================== try { uint y =checked(x+1); //unint y =unchecked(x+1); Console.WriteLine(y);//如果使用了unchecked 则输出0 不进catch , C#默认使用unchecked } catch(OverflowException) { Console.WriteLine("There's a overflow!"); } } }
- 上下文用法
class Program { public static void Main(string[] args) { uint x = uint.MaxValue; Console.WriteLine(x); string binStr=Convert.ToString(x,2); Console.WriteLine(binStr); checked/unchecked { try { uint y = x+1; Console.WriteLine(y);// C#默认使用unchecked } catch(OverflowException) { Console.WriteLine("There's a overflow!"); } } } }
-
delegate 关键字
-
声明委托
-
当操作符使用 (lambda表达式取代了此作用)
匿名方法
-
新建一个WPF程序
-
初始化界面
-
写Click事件
- 正常情况
public partial class MainWindow:Window { public MainWindow() { InitializeComponent(); this.myButton.Click+=myButton_Click; } void myButton_Click(object sender,RoutedEventArgs e) { this.myTextBox.Text="Hello,World"; } }
- 当按钮触发事件myButton_Click不会被重用的情况下,可以使用匿名方法
- 使用delegate操作符
- lambda表达式
public partial class MainWindow:Window { public MainWindow() { InitializeComponent(); //使用delegate操作符声明了一个匿名方法 this.myButton.Click+= delegate (object sender,RoutedEventArgs e) { this.myTextBox.Text="Hello,World"; }; //使用lambda表达式声明匿名方法 this.myButton.Click+=(sender,e)=> { this.myTextBox.Text="Hello,World"; }; } }
-
-
-
"sizeof"操作符
-
只能获取结构体数据类型的实例在内存中所占字节数 , !!! string , object 不行
-
在非默认情况下,可以使用sizeof获取自定义结构体类型的实例在内存中占的字节数(需要把它放在不安全的上下文中)
int x = sizeof(int); Console.WriteLine(x);//4 int y = sizeof(long); Console.WriteLine(y);//8 int z = sizeof(ulong); Console.WriteLine(z);//8
自定义
class Program { static void Main(string[] args) { unsafe //项目.项目属性.build>允许不安全代码 { int x = sizeof(Student); Console.WriteLine(x); //16 } } } struct Student { int ID; long Score; }
-
-
“->”
指针,取地址,用指针访问成员操作只能操作结构体类型
class Program { static void Main(string[] args) { unsafe { Student stu; stu.ID=1; stu.Score=99; Student* pStu= &stu; pStu->Score=100; Console.WriteLine(stu.Score); } } struct Student { public int ID; public long Score; }
一元操作符
-
&x
-
*x
unsafe { (*pStu).Score=1000; }
-
-
int x=int.MinValue; int y=-x; //int y=checked(-x); Console.WriteLine(x); Console.WriteLine(y);
-
!
bool b1=true; bool b2=!b1; Console.WriteLine(b2);//false
class Program { static void Main(string[] args) { } class Student(string initName) { public Student(string initName) { if(!string.IsNullOrEmpty) {this.Name=initName;} else {throw new ArgumentException("initName cannot be null or Empty.");} } public string Name; }
-
~ 求反操作符 二进制按位取反
int x=12345678; int y= ~x; Console.WriteLine(y);// -12345679 // ??? string xStr=Convert.ToString(x,2).PadLeft(32,'0'); string yStr=Convert.ToString(y,2).PadLeft(32,'0'); Console.WriteLine(xStr); Console.WriteLine(yStr);
-
++ 前置自增
-
– 前置自减
单独使用 ++x/–x <=> x++/x–
int x =100; x++; Console.WriteLine(x);
一旦有赋值 则 不可
int x= 100; int y= x++; Console.WriteLine(x);//101 Console.WriteLine(y);//100 //=========================== int x= 100; //x=x+1; int y= ++x;// --x同理 Console.WriteLine(x);//101 99 Console.WriteLine(y);//101 99
-
(T)x
类型转换
-
隐式类型转换
- 不丢失精度的转换 long 8-64
int x =int .MaxValue; long y=x; Console.WriteLine(y);//小精度到大精度
- 子类向父类的转换(面向对象)
class Program { static void Main(string[] args) { Teacher t=new Teacher(); Human h= t;//子类向父类的隐式类型转换 //t.Teach/Think/Eat //h.Think/Eat (当用引用变量访问实例的时候 只能访问到变量类型所具有的成员) Animal a=h; } } class Animal { public void Eat() { Console.WriteLine("Eating"); } } class Human:Animal { public void Think() { Console.WriteLine("Who I am?"); } } class Teacher:Human { public void Teach { Console.WriteLine("I teach Programming"); } }
- 装箱(值类型的实例从栈里移到堆里,性能损失 精度不会损失)
-
显示类型转换
-
有可能丢失精度(甚至发生错误的转换) cast —T(X)
//ushort 16位 表示的最大值65535 uint 32位 Console.WriteLine(ushort.MaxValue); uint x =65536; //(00000..1)|(0000...0) ushort y =(ushort)x; Console.WriteLine(y);//0
-
拆箱
-
使用Convert类
string str1=Console.ReadLine(); string str2=Console.ReadLine(); int x= Convert.ToInt32(); int y= Convert.ToInt32(); Console.WriteLine(x+y);
-
ToString 方法与各数据类型的Parse/TryParse方法 , Convert.ToString()
- ToString
double x =System.Convert.ToDouble(tb1.Text); double y =System.Convert.ToDouble(tb2.Text); double result=x+y; //this.tb3.Text=System.Convert.ToString(result); this.tb3.Text=result.ToString(); //object o ; //o.Equals/GetHashCode/GetType/ToString
- Parse 只能转换符合格式的字符串类型
double x = double.Parse(this.tb1.Text); double y = double.Parse(this.tb2.Text); double result=x+y; this.tb3.Tex t=result.ToString();
-
-
自定义类型转换操作符
-
示例
class Program{ static void Main(string[] args) { Stone stone=new Stone(); //Monkey m=(Monkey)stone;//不能转 stone.Age=5000; Monkey wukongSun=(Monkey)stone; Console.WriteLine(wukongSun.Age); } } class Stone { public int Age; //显式 public static explicit operator Monkey(Stone stone) { Monkey m=new Monkey(); m.Age=stone.Age/500; return m; } } class Monkey { public int Age; }
-
算术运算符
- 操作的数据类型不同 行为不同
- 取余
- 留心“数值提升” 数据类型
-
乘法
-
乘法
- 整数乘法
var x= 3*4; Console.WriteLine(x.GetType().FullName);//System.Int32 Console.WriteLine(x);//12
- 浮点乘法
var x= 3.0*4.0; Console.WriteLine(x.GetType().FullName);//System.Double Console.WriteLine(x);//12
var x= 3.0*4;//数值提升 Console.WriteLine(x.GetType().FullName);//System.Double Console.WriteLine(x);//12
int x=100; double y=x;//不丢精度 Console.WriteLine(y);
- 小数乘法
-
除法
-
整数除法
int x = 5; int y = 4;// y=0 除0异常 DevideByZeroException int z = x/y ; Console.WriteLine(z);// 1
-
浮点除法
double x = 5.0;//x=5.0 x=-5.0 double y = 4.0;//y=0 double z = x/y;//z=∞ z=-∞ Console.WriteLine(z); // 1.25 //取正负无穷? double a = double.PositiveInfinity; double b = double.NegativeInfinity; double c= a/b; Console.WriteLine(c);//NaN
double x=(double)5/4; //类型提升 类型转换操作符是一元操作符 优先级大于除法 COnsole.WriteLine(x); //1.25 double x =(double)(5/4); int的1=>double Console.WriteLine(x); //1-double
-
小数除法(decimal)
-
-
取余操作符 “%”
-
整数取余
for(int i=0; i<100; i++) { Console.WriteLine(i%10); } //0123456789...6789
-
浮点取余 也涉及类型提升
double x=3.5; double y=3; Console.WriteLine(x%y);//0.5
-
小数取余
-
-
-
加法 做加减也会产生类型提升
-
整数
-
浮点
-
小数
-
连接字符串
-
操作委托
“+∞ ” + “-∞”= NaN
var x=3.0+4; Console.WriteLine(x.GetType().Name);//System.double Console.WriteLine(x);// 7 -double
string s1="123"; string s2="abc"; string s3=s1+s2; Console.WriteLine(s3); // 123abc
-
-
减法
-
整数
-
浮点
-
小数
“+∞” - “+∞” =NAN
-
移位操作符 << >>
数据在内存中二进制的结构向左或向右平移
左移操作无论正负数 皆是补0
右移
- 正数 最高位补0
- 负数 最高位补1
未溢出情况下
左移乘2
右移除2
-
左移
int x=7; int y= x<<1;//x<<2 string strX=Convert.ToString(x,2).PadLeft(32,'0'); string strY=Convert.ToString(y,2).PadLeft(32,'0'); Console.WriteLine(strX);//000....0111 Console.WriteLine(strY);//000....1110 //000...11100 --28
-
右移
int x=7; int y= x>>2;// string strX=Convert.ToString(x,2).PadLeft(32,'0'); string strY=Convert.ToString(y,2).PadLeft(32,'0'); Console.WriteLine(strX);//000....0111 Console.WriteLine(strY);//000....0001 --1
关系操作符
所有关系操作符的运算结果都是bool类型的
-
-
- 关系和类型检测 < > <= >= is as (谁大谁小)
可用于操作比较数值类型 (整数、浮点)
int x=5;
double y=4.0;
var result = x>y ;// >=
Console.WriteLine(result.GetType().FullName);//System.Boolean
Console.WriteLine(result);//True
可用于操作比较字符类型 (char)
char char1='a';
char char2='A';
var result = char1 > char2; //>= <= == !=
Console.WriteLine(result);//true
char类型归于整数类型
char用两个字节 16位保存一个无符号短整型的数 -对应Unicode上的一个字符
char char1='a';
char char2='A';
ushort u1=(ushort)char1;
ushort u2=(ushort)char2;
Console.WriteLine(u1);//97
Console.WriteLine(u2);//65
- 相等 == != (是否相等)
string str1="abc";
string str2="Abc";
Console.WriteLine(str1==str2);//False
Console.WriteLine(str1.ToLower()==str2.ToLower());//True
//string.Compare()
- “is” “as” 类型检验操作符
- is
class Program
{
static void Main(string[] args)
{
Teacher t=new Teacher();
var result=t is Teacher;//Human..//Animal
Console.WriteLine(result.GetType().FullName);//System.Boolean
Console.WriteLine(result);//true
//==========================================
Teacher t2 = null;
var result2=t2 is Teacher;
Console.WriteLine(result2);//false
//==========================================
Car car=new Car();
Console.WriteLine(car is object);//true
Console.WriteLine(car is Animal);//false
//===========================================
Human h=new Human();
var result= h is Teacher;
Console.WriteLine(result); //false
}
}
class Animal
{
public void Eat()
{
Console.WriteLine("Eating");
}
}
class Human:Animal
{
public void Think()
{
Console.WriteLine("Who I am?");
}
}
class Teacher:Human
{
public void Teach
{
Console.WriteLine("I teach Programming");
}
}
class Car
{
public void Run()
{
Console.WriteLine("Runing...");
}
}
- as
class Program
{
static void Main(string[] args)
{
Object o=new Teacher();
/* if(o is Teacher)
{
Teacher t =(Teacher)o;
t.Teach();
}
*/
Teacher t=o as Teacher;
if (t!null)
{
t.Teach();// I teach Programming
}
}
}
class Animal
{
public void Eat()
{
Console.WriteLine("Eating");
}
}
class Human:Animal
{
public void Think()
{
Console.WriteLine("Who I am?");
}
}
class Teacher:Human
{
public void Teach
{
Console.WriteLine("I teach Programming");
}
}
class Car
{
public void Run()
{
Console.WriteLine("Runing...");
}
}
位与 & 、位异或 ^,或 |
-
&
int x=7; int y=28; int z= x & y; string strX=Convert.ToString(x,2).PadLeft(32,'0'); string strY=Convert.ToString(y,2).PadLeft(32,'0'); string strZ=Convert.ToString(z,2).PadLeft(32,'0'); Console.WriteLine(strX);//0000000...000111 Console.WriteLine(strY);//0000000...011100 Console.WriteLine(strZ);//0000000...000100
-
^ 两位不一样的时候才是真
int x=7; int y=28; int z= x ^ y; string strX=Convert.ToString(x,2).PadLeft(32,'0'); string strY=Convert.ToString(y,2).PadLeft(32,'0'); string strZ=Convert.ToString(z,2).PadLeft(32,'0'); Console.WriteLine(strX);//0000000...000111 Console.WriteLine(strY);//0000000...011100 Console.WriteLine(strZ);//0000000...011011
-
|
int x=7; int y=28; int z= x | y; string strX=Convert.ToString(x,2).PadLeft(32,'0'); string strY=Convert.ToString(y,2).PadLeft(32,'0'); string strZ=Convert.ToString(z,2).PadLeft(32,'0'); Console.WriteLine(strX);//0000000...000111 Console.WriteLine(strY);//0000000...011100 Console.WriteLine(strZ);//0000000...011111
条件与 && 条件或 ||
操作布尔类型值 并且返回一个布尔类型的值
-
&&
A&&B 当且仅当A,B全True 返回True
int x = 5; int y = 4; int a = 100; int b = 200; if(x>y && a<b) { Console.WriteLine("Hello");//输出Hello }
-
||
A||B A,B有一个True 则返回True
int x = 3; int y = 4; int a = 100; int b = 200; if(x>y || a<b) { Console.WriteLine("Hello");//输出Hello }
-
条件与&& 的 “短路效应” 尽量规避
int x = 3; int y = 4; int a = 3; if(x>y && a++>3) //左边不满足 直接跳出if 但是如果x=5 依然跳出if 但是会打印a=4 { Console.WriteLine("Hello");//输出Hello } Console.WriteLine(a);//3
-
条件或|| 的**“短路效应”** 尽量规避
int x = 5; int y = 4; int a = 3; if(x>y || a++>3) //左边满足 { Console.WriteLine("Hello");//输出Hello } Console.WriteLine(a);//输出打印3
int x = 3; int y = 4; int a = 3; if(x>y || ++a>3) //左边满足 { Console.WriteLine("Hello");//输出Hello } Console.WriteLine(a);//输出打印4
NULL合并 ??
-
a
//int x; //x=null;// 错误写法 整数类型变量不接收null值
-
3.0引入写法
Nullable<int> x =null; x=100; Console.WriteLine(x);//100 Console.WriteLine(x.HasValue);//true //=================================== Nullable<int> x =null; Console.WriteLine(x.HasValue);//false
-
因为Nullable常用,将其吸收为关键字
int?x=null; x=100; Console.WriteLine(x);//100 Console.WriteLine(x.Value);//100
没交作业给1分
int?x=null; int y=x??1; Console.WriteLine(y);//1
以上是 C#的复习笔记 参考 Timothy Liu的C#课程