c#之操作符
1.操作符概览
下面图中的优先级是从上往下递减,同行是从左往右递减。
操作符的本质就是函数(算法);比如说没有操作符+,那么我们做加法的时候只能先写一个Add方法,然后调用。
操作符不能脱离与它相关联的数据类型;
比如下面的代码:
int a=1; int b=2; int c=a/b;
c的结果一定是整数,因为这里的除号是int类型的除号。
但是如果是下面这种,那么就是精度高的除号,也就是double的除号:
double a = 1; int b = 2; double c = a / b;
(1)自定义一个操作符
下面代码实现了2个人结婚,并且婚后有很多孩子。
namespace TestClass { // class Program { static void Main(string[] args) { Person person1 = new Person(); Person person2 = new Person(); person1.Name = "Deer"; person2.Name = "Deer's wife"; List<Person> people = Person.GetMarry(person1,person2); foreach(var item in people) { Console.WriteLine(item.Name); } Console.ReadKey(); } } class Person { public string Name { get; set; } /// <summary> /// 结婚之后生孩子 /// </summary> /// <param name="person1"></param> /// <param name="person2"></param> /// <returns></returns> public static List<Person> GetMarry(Person person1, Person person2) { List<Person> people = new List<Person>(); people.Add(person1); people.Add(person2); for (int i = 0; i < 11; i++) { Person child = new Person() { Name = person1.Name + "&" + person2.Name + "s child" }; people.Add(child); } return people; } } }
就像之前说的,操作符的本质是算法的简记法。所以可以重写自定义的+号来表示。
namespace TestClass { // class Program { static void Main(string[] args) { Person person1 = new Person(); Person person2 = new Person(); person1.Name = "Deer"; person2.Name = "Deer's wife"; List<Person> people = person1 + person2; foreach(var item in people) { Console.WriteLine(item.Name); } Console.ReadKey(); } } class Person { public string Name { get; set; } /// <summary> /// 结婚之后生孩子 /// </summary> /// <param name="person1"></param> /// <param name="person2"></param> /// <returns></returns> public static List<Person> operator + (Person person1, Person person2) { List<Person> people = new List<Person>(); people.Add(person1); people.Add(person2); for (int i = 0; i < 11; i++) { Person child = new Person() { Name = person1.Name + "&" + person2.Name + "s child" }; people.Add(child); } return people; } } }
结果:
Deer Deer's wife Deer&Deer's wifes child Deer&Deer's wifes child Deer&Deer's wifes child Deer&Deer's wifes child Deer&Deer's wifes child Deer&Deer's wifes child Deer&Deer's wifes child Deer&Deer's wifes child Deer&Deer's wifes child Deer&Deer's wifes child Deer&Deer's wifes child
(2)操作符的优先级
可以使用圆括号提高被括起来表达式的优先级。
同优先级操作符的运算顺序
除了带有赋值功能的操作符,同优先级操作符都是由左向右进行运算,
带有赋值运算的操作符的运算顺序都是由右向左,比如“=”,“+=”
计算机的同优先级运算符没有结合律。比如1+2+3;就是按照除了带有赋值功能的操作符之外同优先级的从左往右的顺序进行计算的,不存在是先2+3还是1+2;
比如:
int x; x=1+3*4;
因为加减乘除的运算法优先级大于赋值运算符,所以先算3*4,然后1+3*4,最后赋值给x;
下面的是赋值操作符,所以从右向左:
int x = 1; int y = 2; int z = 3; z += y += x; Console.WriteLine(x); Console.WriteLine(y); Console.WriteLine(z);
结果:
1
3
6
(3)匿名类型,匿名方法
new关键字可以创建实例之外还可以创建匿名类型,比如:
List<string> list = new List<string>(); var test = new { ID = 1, Name = list };
var v = new[] {
new { Name = "Micro", Message = "Hello" },
new { Name = "Soft", Message = "Wold!" }
};
new关键字不要乱用,因为他在创建一个实例的时候,就会把2个类的耦合加深,一旦其中一个类出了问题,就可能会造成其他的影响。、
匿名方法是和委托一起使用的,下面就是匿名方法的一个例子:
class Program { delegate void TestDelegate(string s); static void Main(string[] args) { TestDelegate testDelB = delegate (string s) { Console.WriteLine(s); }; } }
(4)checked与unchecked
这个2个操作符是用来检查是否出现内存溢出,默认的都是unchecked。
下面代码是检查是否溢出的,如果溢出就会报错,
try { int x = int.MaxValue; int y = checked(x + 1); Console.WriteLine(y); } catch (OverflowException x) { Console.WriteLine(x.Message); }
如果是:int y = unchecked(x + 1);结果是:-2147483648,此时会变成最小值赋给y。
还可以用下面的形式来写:
checked { try { int x = int.MaxValue; int y = x + 1; Console.WriteLine(y); } catch (OverflowException x) { Console.WriteLine(x.Message); } }
(5)sizeof
在默认情况下,sizeof只能获取结构体类型(比如int,long,decimal,short,char,float,bool,byte)的实例对应的字节数,object和string不行。在非默认情况下可以获取自定义类型的结构体的实例在内存中占的字节数,但是需要放到不安全上下文中。
默认情况下:
int x = sizeof(byte);
非默认情况下:前提要修改项目的属性,允许使用不安全代码
class Program { static void Main(string[] args) { unsafe { try { int x = sizeof(byte); int y = x; Console.WriteLine(y); } catch (OverflowException x) { Console.WriteLine(x.Message); } } Console.ReadKey(); } } struct Student { int ID; long Score; }
(6)正负操作符:-
int x = int.MinValue; int y = -x; Console.WriteLine(y); Console.WriteLine(x);
-这个操作符表示正负操作符,比如x值是7,int y=-x;结果就是-7。看上面的代码,之所以出现这个问题,是因为int的正负值的绝对值大小是不对称的。int
的值范围是-2147483648到2147483647,-2147483648使用了正负操作符之后变成了2147483648,造成内存溢出。
结果:
-2147483648
-2147483648
(7)取反操作符:~
在计算机中取相反数是按位取反再加一。
int x = 12345678; int y = ~x; Console.WriteLine(y);
结果:-12345679
(8)取非操作符:!
bool f = false; bool f1 = !f; Console.WriteLine(f1);
(9)自定义的类型转换
namespace TestClass { // class Program { static void Main(string[] args) { Stone stone = new Stone(); stone.Age = 5000; Monkey monkey = (Monkey)stone; Console.WriteLine(monkey.Age); Console.ReadKey(); } } class Monkey { public int Age { get; set; } } class Stone { public int Age { get; set; } /// <summary> /// 显示转换自定义类型 /// 隐式的话将explicit改成implicit即可。 /// </summary> /// <param name="stone"></param> public static explicit operator Monkey(Stone stone) { Monkey monkey = new Monkey(); monkey.Age = stone.Age / 500; return monkey; } } }
引自于:https://www.bilibili.com/video/BV13b411b7Ht?p=10