Day4
---|*十*|---
操作符本质
操作符(operator)也称运算符
操作符的本质是对算法(函数)的简记
有乘法符号*后,3+3+3+3,可简记为3*4
操作符不能脱离与它关联的数据类型
同样是除法运算,但输出结果不一样,因为他的操作符与数据类型绑定。前者是int型,后者是double型。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
internal class Program
{
static void Main(string[] args)
{
int x = 6; int y=5;
int z = x/y;
Console.WriteLine(z);
double a = 6.0; double b = 5.0;
double c =a/b;
Console.WriteLine (c);
}
}
}
优先级由上向下降低
基本运算符
点操作符:又叫成员访问操作符,可以访问 外层名称空间中的子集名称空间、名称空间中的类型、类型中的静态成员、对象的成员
System.IO.File.Create("D:\\ooooooo.txt");//在D盘中创建了ooooooo.txt文件
//System.IO.File.Create名称空间.子集名称空间.类.静态方法
f():方法调用操作符,并不是所有情况用到方法都带();比如委托就不用。
元素访问操作符:a[ ],它的方括号里可以是整形,也可以是字符串,比如在泛型 集合索引中可以是字符串。
y=x++相当于y=x;x=x+1
y=++x相当于x=x+1;y=x
typeof运算符
用来查看类型的内部结构(如其名字、父类名字、属性、方法)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp6
{
internal class Program
{
static void Main(string[] args)
{
Type t = typeof(int);
Console.WriteLine(t.Namespace);
Console.WriteLine(t.Name);
Console.WriteLine(t.FullName);
int c=t.GetMethods().Length;//打印出int中方法数量
foreach (var mi in t.GetMethods())//打印int所有的方法
{
Console.WriteLine(mi.Name);
}
Console.WriteLine(c);
}
}
}
default方法
用来获取 类型的默认值。
结构体类型:获取来的是0
引用类型:获取来的是null
枚举类型:获得的是为零的值
情况一:
枚举类型在声明时与数值对应,Mid与0对应,Low与1对应,High与2对应,则会输出Mid
“类似输出level[0]”
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp7
{
internal class Program
{
static void Main(string[] args)
{
Level level = default(Level);
Console.WriteLine(level);
}
}
enum Level
{
Mid,
Low,
High
}
}
情况二:
枚举类型可以对成员显性的赋值,为High赋值0,则输出High。“类似输出level[0]”
namespace ConsoleApp7
{
internal class Program
{
static void Main(string[] args)
{
Level level = default(Level);
Console.WriteLine(level);
}
}
enum Level
{
Mid=6,
Low=4,
High=0
}
}
情况三:
所有成员都赋值了,但未有赋0的,那么逻辑就出错了,要避免这种错误,设置时要有0.
namespace ConsoleApp7
{
internal class Program
{
static void Main(string[] args)
{
Level level = default(Level);
Console.WriteLine(level);
}
}
enum Level
{
Mid=6,
Low=4,
High=8
}
}
new操作符
var用来声明隐式变量。给它赋值后,才确定数据类型。
C#是强数据类型,当变量确定了数据类型后就不能再改变类型。
new用来创建实例,并且调用构造器,能将实例内存地址赋给变量。
new还能调用初始化器 Form myForm = new Form(){Text="Hello"}
Form myForm = new Form()详解
new Form//表示创造Form实例
new Form()//表示创造Form实例,并且调用构造器。此时无谁引用它,很快就会被回收。
Form myForm = new Form()//声明一个Form引用变量,引用右边的实例。
//可知new将实例的内存地址,赋值给了变量。
变量便可访问实例了
💡 new Form(){Text="Hello"}.ShowDialog();
/没有变量引用Form,使用一次,就很快会被回收。符合实际开发情景
💡创造实例,不是必须要new
如String是类类型,创建实例时,应当new。但其是基本类型,微软就将new隐藏了,减少麻烦。
还有数组类型创建实例时,int[ ] myArray= new int[10]; 可以写成 int[ ] myArray={1,2,3,4};
💡new能为匿名类型创建实例,用隐式变量引用该实例
匿名类型创建实例:
var person = new{Name= "Hello",Age=34};//匿名
Form Myform=new Form() {Text="Hello"};//对比非匿名
可看出,new时,无类型名字,直接构造,让系统去猜是啥类型。声明的时var类型,绝配。
具体代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
Form Myform=new Form() {Text="Hello"};
var person = new{Name= "Hello",Age=34};
Console.WriteLine (person.Name);
Console.WriteLine (person.Age);
Console.WriteLine (person.GetType().Name);
}
}
}
💡new会增加类的耦合,小心使用。当然设计模式中有依赖注入,可放松耦合
💡new关键字除了是操作符外,还能是修饰符
checked操作符 unchecked操作符
checked操作符
在C#中,
checked
关键字是一个运算符前缀,它用于指定在整数运算过程中是否启用溢出检查。默认情况下,C#在整数运算时并不检查是否有溢出,如果运算结果超过了整数类型的范围(如int从-2^31到2^31-1),则会发生隐式的类型转换,而不是引发异常。当你在一个表达式前面加上
checked
关键字,C#会在进行算术运算之前先检查结果是否超出类型的最大值。如果计算结果超出了边界,那么C#会抛出一个OverflowException
异常。这是为了提醒开发者防止意外的结果,尤其是在进行敏感数据处理时,可以避免潜在的数据损坏。
例如:
int maxInt = int.MaxValue;
checked {
int result = maxInt + 1; // 这里会抛出OverflowException,因为+1会导致超过最大值
Console.WriteLine(result); // 不会执行到这里
}
unchecked操作符 不用检查一个值在内存中是不是溢出
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
internal class Program
{
static void Main(string[] args)
{
try
{
uint x=uint.MaxValue;
uint y=checked(x+1);//y值溢出
Console.WriteLine(y);
}
catch
{
Console.WriteLine("这里溢出");
}
}
}
}
使用unchecked,则不会爆异常,输出0
以上是操作符用法,也可以上下文用法,如下:
checked
{
try
{
uint x = uint.MaxValue;
uint y = x + 1;//y值溢出
Console.WriteLine(y);
}
catch
{
Console.WriteLine("这里溢出");
}
}
}
delegate操作符
delegate操作符用来声明匿名方法,已被拉姆达表达式取代
一般delegate不用作操作符,而用来声明委托数据类型
sizeof操作符
1、用来获取结构体数据类型在内存中的字节数
2、非默认情况下,可以用来获取自定义的结构体类型的实例,在内存中占的字节数。但需要将sizeof放在一个不安全的上下文当中。
->箭头符号
放在一个不安全的上下文当中,用来操作结构体成员变量
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
internal class Program
{
static void Main(string[] args)
{
unsafe
{
Student stu;
stu.Score = 99;
stu.Id = 1;
Student* pStu =&stu;
pStu->Id = 2;
Console.WriteLine(stu.Id);
}
}
}
struct Student
{
public int Id;
public long Score;
}
}
一元操作符
一元操作符是一种特殊的运算符,它只需要单个操作数就能完成计算。
~求反操作符:按位取反
-求相反数是按位取反再加1
类型转换
隐式类型转换:不丢失精度的转换(小精度向大精度的转换)、子类向父类的转换、装箱
以下代码展示的是,子类Human向父类Animal的转换。
值得注意的是,Animal引用变量B 引用了Human的实例。但是B只能使用Animal的方法。属于human的think方法不能用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp4
{
internal class Program
{
static void Main(string[] args)
{
Human A= new Human();
Animal B = A;
B.Eat();
A.Think();
}
}
class Animal
{
public void Eat()
{
Console.WriteLine("吃饭");
}
}
class Human : Animal
{
public void Think()
{
Console.WriteLine("我是人");
}
}
}
显式类型转换:有可能丢失精度的转换(大精度向小精度的转换)、使用Convert类、ToString方法、各数据类型的Parse/TryParse方法.
String str="hm";
double x=double.Parse(str);
double y=System.Convert.ToString(str);
double result=x+y;
String ss=result.ToString();
自定义类型转换操作符
将stone类转换为monkey类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Cache;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp5
{
internal class Program
{
static void Main(string[] args)
{
Stone stone_y=new Stone();
stone_y.Age = 5000;
Monkey wukong=(Monkey) stone_y;//想将stone类转换为monkey类,则在stone类中操作
Console.WriteLine(wukong.Age);
}
}
class Stone
{
public int Age;
public static explicit operator Monkey(Stone stone_y)//explicit表示显式类型转换,
//改成implecit则为隐式类型转换,并且16行(Monkey) 可省
{
Monkey m=new Monkey();
m.Age = stone_y.Age / 500;
return m;
}
}
class Monkey
{
public int Age;
}
}
算术运算符
数值提升:var x=3.0+4;虽然4是int,但x变成了浮点型,避免丢失精度
移位<< >>的补位机制:左移,无论正数还是负数都自动补0。右移,负数最高位补1,正数最高位补0。
在移位不溢出的情况下,左移,乘2倍。右移,除2倍。
关系运算符
> <<=等等关系运算符都是bool型返回值。
逻辑运算符
-
与(&):都真才真
-
或(|):有真则真
-
异或(^):相同为0,不同为1
条件运算符
逻辑与(&&)短路现象:
当左侧的表达式为假,则整个表达式的值必为假,此时右侧的表达式将不会被执行
逻辑或(||)短路现象:
当左侧的表达式为真,则整个表达式的值必为真,此时右侧的表达式将不会被执行
null合并操作符
int? X = null;//不能直接给int变量设null值,但声明可空类型int?就可以设置null值
int y = X ?? 1;//x是null值则给y赋1
Console.WriteLine(y);
条件操作符
A?B:C A成立则输出B,否则输出C
int x=50;
String str=(x>=60)?"及格":"不及格";