【C#语言入门】08. 操作符详解(上)
一、操作符概览
- 操作符(Operator)也译为“运算符”
- 操作符是用来操作数据的,被操作符操作的数据称为操作数(Operand)
类别 | 运算符 |
---|---|
基本 | x.y f(x) α[x] x++ x-- new typeof default checked unchecked delegate sizeof -> |
一元 | + - ! ~ ++x --x (T)x await &x * x |
乘法 | * / % |
加减 | + - |
位移 | << >> |
关系和类型检测 | < > <= >= is as |
相等 | == != |
逻辑“与” | & |
逻辑“异或” | ^ |
逻辑“或” | | |
条件“and” | && |
条件“or” | || |
null合并 | ?? |
条件 | ?: |
赋值和lambda表达式 | = *= /= %= += -= <<= >>= &= ^= |= => |
越靠上的操作符运算优先级越高,同一行的运算优先级相同,相同的运算优先级大多数则按照从左到右依次运算,赋值运算除外。
二、操作符的本质
- 操作符的本质是函数(即算法)的“简记法”
- 假如没有发明“ + ”,而是只有Add函数,那么式子3 + 4 + 5就只能写成Add(Add(3, 4), 5)
- 假如没有发明“ x ”,而是只有Mul函数,那么式子3 + 4 x 5就只能写成Add(3, Mul(4, 5))
- 操作符不能脱离与它关联的数据类型
- 可以说操作符就是与固定的数据类型相关联的一套基本算法的简记法
int x = 5;
int y = 4;
int z = x/y;
Console.WriteLine(z);
//结果为0,因为是整型,和数学上的不一样,所以说操作符不能脱离与它关联的数据类型。
double a = 5.0;
double b = 4.0;
double c = a / b;
Console.WriteLine(c);
//结果为1.25,因为是双精度类型。
namespace CreateOperator
{
internal class Program
{
static void Main(string[] args)
{
Person person1 = new Person();
Person person2 = new Person();
person1.Name = "John";
person2.Name = "Jerry";
List<Person> nation = person1 + person2;
foreach (var p in nation)
{
Console.WriteLine(p.Name);
}
}
}
class Person
{
public string Name;
public static List<Person> operator +(Person p1, Person p2)
{
List<Person> people = new List<Person>();
people.Add(p1);
people.Add(p2);
for (int i = 0; i < 11; i++)
{
Person child = new Person();
child.Name = p1.Name + "&" + p2.Name + "'s " + "child";
people.Add(child);
}
return people;
}
}
}
在上述程序中加号变成了Person类中的一个方法,再次说明了操作符的本质就是方法。
三、优先级与运算顺序
- 操作符的优先级
- 可以使用圆括号提高被括起来表达式的优先级
- 圆括号可以嵌套
- 不像数学里有方括号和花括号,在C#语言中“[]”和“{}”有专门的用途,不会用于提高优先级
- 同优先级操作符的运算顺序
- 除了带有赋值功能的操作符,同优先级操作符都是由左向右进行运算
- 带有赋值功能的操作符的运算顺序是由右向左
- 与数学运算不同,计算机语言的同优先级运算没有“结合律”:3+4+5只能理解为Add(Add(3, 4), 5),而不能理解为Add(3, Add(4, 5))
运算优先级是按照操作符表从上至下依次降低的,最高的操作符优先级最高。
int x;
x = 3 + 4 + 5;
//运算顺序为先3+4,然后7+5,然后再把12赋值(=)给x
int x = 100;
int y = 200;
int z = 300;
x += y += z;
//运算顺序为先y = y + z,然后x = x + y
四、各类操作符的示例
- x.y(成员访问操作符)
System.IO.File.Create("D:\\HelloWorld.txt");
//访问外层名称空间的子集名称空间,访问名称空间的类型,访问类型的静态成员
Form myForm = new Form();
myForm.Text = "Hello,World!";
myForm.ShowDialog();
//访问对象的成员
- f(x)(方法调用操作符)
“f”是函数(function)的缩写,圆括号内的“x”是方法的参数
class Program
{
static void Main(string[] args)
{
Calculator c = new Calculator();
double x = c.Add(3.5, 5.3);
Console.WriteLine(x);
}
}
class Calculator
{
public double Add(double a, double b)
{
return a + b;
}
public void PrintHello()
{
Console.WriteLine("Hello!");
}
}
没有参数的方法的方法调用符也是不可以省略的例如上述的PrintHello方法,但是如果用委托间接的调用一个无返回值无参数的方法的话,是可以省略方法调用符的。
- α[x](元素访问操作符)
访问集合中的元素,常见的有访问数组元素和字典元素,x不一定是整数,x是索引。
int[] myIntArray = new int[10]
//表示这个数组有十个元素,且全部初始化(int类型的初始化值为0)
int[] myIntArray = new int[]{1, 2, 3, 4}
//手动赋值,数组个数等于你赋值的个数
int[] myIntArray = new int[4]{1, 2, 3, 4}
//或者都写,但是个数要与赋值个数相同
Console.WriteLine(myIntArray[0]);
//调用↑
class Program
{
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;
stuDic.Add(stu.Name, stu);
}
Student number6 = stuDic["s_6"];
Console.WriteLine(number6.Score);
}
}
class Student
{
public string Name;
public int Score;
}
可以看到上述例子里面字典的索引并不是整数而是“s_6”。
- x++ / x–(后置的自增/自减)
int x = 100;
x++;
//相当于x = x + 1;
x--;
//相当于x = x - 1;
自增自减的要点在于,他遇到赋值时,先赋值后增减。
- typeof
作用是查看一个类型的内部结构(Metadata),包含数据的基本信息。
Type t = typeof(int);
Console.WriteLine(t.Namespace);
Console.WriteLine(t.FullName);
Console.WriteLine(t.Name);
int c = t.GeyMethods().Length;
foreach (var mi in t.GetMethods())
{
Console.WriteLine(mi.Name);
}
Console.WriteLine(c);
- default
作用是获取类型的默认值
int x = default(int);//结果为0
double y = default(double);//结果还是0
Form myForm = default(Form);//结果为null