0%

c#基础学习

c#学习

C# csharp
Microsoft 专为.NET推出的高级编程语言。
从语言技术、风格、严谨性等特点上来说,c#可成为诸多编程语言中最为优秀的一款,甚至由它而引发出计算机语言界中的多种新规范和新特征。

Mono
Novell公司支持在其他操作系统下开发.NET程序的框架。
Unity借助Mono实现跨平台,Mono提供了微软的.Net框架另一种实现,其核心还是.NET Framework 框架。

CLS

公共语言规范 Common Language Specification:

定义了.NET平台上运行的语言所必须支持的规范,用以避免不同语言特性产生的错误,实现语言间互操作。
CLR
公共语言运行库 Common Language Runtime:
程序的运行环境,负责内存分配、垃圾收集、安全检查等工作。
.Net程序编译过程
计算机语言发展史
第一代语言:机器语言
第二代语言:汇编语言
第三代语言:高级语言
编译运行过程:
源代码–(CLS编译)->CIL(通用中间语言)–(CLR编译)->机器码

语法

1.声明变量
1).声明:在内存中开辟一块空间
声明类型 变量名;
2). 命名规则
以小写字母开头。
如果包含多个单词,除第一个单词外其他单词首字母大写。
增加类型前缀便于理解。
例如 string studentName;
2.赋值:在该空间存储数据
变量名=数据;(=这个符号从今天开始表示赋值)
注:
局部变量在使用前必须赋值。
赋值的数据类型和变量声明时的类型必须相同。
同一变量名只能声明一次,但可以多次赋值。
占位符
在字符串中插入变量,如下所示
string name = “张三”;
int hp = 120;
Console.WriteLine(“用户名为:{0},生命值为:{1}”,name,hp);
用法:
string str = string.Format(“用户名为:{0},生命值为:{1}”, name, hp);
Console.WriteLine(str);
转义字符
//我爱”Unity” 打印这句话
Console.WriteLine(“我爱”Unity””);
//表示单引号
char c = ‘’’;

标识符

1.什么是标识符?
标识符是开发人员(程序员)对程序中的各个元素命名时使用的字符序列。元素包括:类、方法、变量、常量等元素。

2.标识符命名规则
标识符应遵循以下具体规则:

标识符由大小写字母、数字、下划线、@等组成;
标识符不能以数字开头,除数字外,其它几种都允许;
C#严格区分大小写,即:大写和小写被认为有不同含义;
不能使用C#的关键字或保留字,除非它们前面加@前缀;
标识符必须不包含任何嵌入的空格或符号,比如 :
  ? - +! # % ^ & * ( ) [ ] { } . ; : “ ’ / \。 
注:随着版本不断升级,C#中可识别的标识符种类也越来越多,比如:汉字可作为变量名,类名等,但是不推荐。

Day1

算数运算符

对数值类型(整形、非整形)进行算数运算的符号。
包括:加+ 减- 乘* 除/ 取模%
int a = 5, b = 2;
int c = a / b; —结果为 2
int c=a%b; —结果为1
注:取模%可以判断数字是否能被另一个数字整除
String类型可以使用+,意为字符的拼接。
string s1 = “5”, s2 = “2”;
string s3 = s1 + s2; —结果为 “52”

比较运算符

判断数值间大小关系的符号。
包括:大于> 小于< 大于等于>=
小于等于<= 等于== 不等于!=
bool isEqual =1 !=2; —true
String类型可以使用 == 和 !=,意为文本是否相同。

逻辑运算符

判断 bool 值关系的符号。
参与逻辑运算的变量或表达式都是bool类型,结果也为bool类型。
bool result01= true && true;
bool result02 = 2 > 3 || 1 != 1;

&& :表示“并且” 的关系,一假俱假。
|| :表示“或者” 的关系,一真俱真。
! :表示“取反”。

短路逻辑

—对于&&运算符,当第一个操作数为false时,将不会判断第二个操作数,因为此时无论第二个操作数为何,最后的运算结果一定是false。
—对于||运算符,当第一个操作数为true时,将不会判断第二个操作数,因为此时无论第二个操作数为何,最后的运算结果一定是true。
快捷运算符
一个变量与另外一个值做算数运算后的结果再赋值给该变量,可以使用快捷运算符。
包含:+= -= *= /= %=
int num=1;
num = num + 1; ==> num += 1;

一元运算符

操作数只有1个的运算符。
自增()和自减(–):使变量自身增加1或减少1。
int i = 1;
i;
Console.WriteLine(i); — 2
后缀增量操作i++: 返回的结果为自增以前的值。
前缀增量操作++i:返回的结果为自增以后的值。

三元运算符

具有3个操作数的运算符。
结构为:
数据类型 变量名 = 条件? 结果1:结果2;
规则:
先计算bool条件,为true返回结果1,为false返回结果2
string strResult = 1 > 2 ? “对了”:”错了”;

位运算符

位运算符作用于位,并逐位执行操作。即:进行位运算时,应该先将参与运算的数据转为二进制类型,然后再运算。&、 | 和 ^ 的真值表如下所示:

假设若 A = 60,且 B = 13,现在以二进制格式表示:
60的二进制: 0 0 1 1 1 1 0 0
13的二进制: 0 0 0 0 1 1 0 1

A&B = 0 0 0 0 1 1 0 0
A | B = 0 0 1 1 1 1 0 1
A^B = 0 0 1 1 0 0 0 1
~A = 1 1 0 0 0 0 1 1 

其他运算符

typeof:返回 class 的类型。
sizeof:返回数据类型的大小(在内存中所占字节数)
is:判断对象是否为某一类型。
as:强制转换,即使转换失败也不会抛出异常。  

下表将按运算符优先级从高到低列出各个运算符,如下:

数据类型转换

ToString转换

任意类型转换为字符串类型。
int num = 100;
string strNumber = num.ToString();

Pares转换

字符串类型转换为其他类型
string strNumber = “100”;
int num = int.Parse(strNumber);
若字符串未被识别为该类型的有效值,则程序抛异常。
int number01 = int.Parse(“1.0”);
float number02= float.Parse(“1.0f”);

代码和作用域

在程序中可以使用一对大括号框住一部分代码,被框住的代码区域称之为代码块。
作用域可以理解为起作用的范围。
局部变量作用域:从声明开始,到所属 } 结束。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1. static void Main()
{
int a = 1;
{
int a = 2;//原来的a依然存在,所以程序错误
}
}
2. static void Main()
{
{
int a = 1;
}
Console.WriteLine(a);//超过a的作用域,所以程序错误
}

If else语句

1.判断语句

格式: if结构只考虑条件为真的情况。

注:条件语句判断语句是 逻辑判断 ==、!=、>=、<=、>、<

1
2
3
4
if(true)
{
Console.WriteLine("我被执行了!");
}
1
2
3
4
5
6
int a=1;
int b=2;
if(a<b)
{
Console.WriteLine("a小于b,我被执行了!");
}

2 .if-else语句

if-else语句允许在两个程序块之间进行选择,同样无论条件的值如何,都能有且只有一种选择被执行。
注:从上到下为并列关系,if else if只要有一个判断正确,后面的else if就不再执行。

1
2
3
4
5
6
7
8
if(true)
{
Console.WriteLine("我被执行了!");
}
else
{
Console.WriteLine("上面被执行了,我不会被执行了!");
}

3 . if-else if语句

注:条件表达式1;false&&条件表达式2;true。执行第二条表达式中的语句块。
else执行时说明所有条件都不满足。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(条件表达式1)	
{
Console.WriteLine("如果我的判断条件是对的,我执行");
}

else if(条件表达式2)
{
Console.WriteLine("如果上面没有被执行了,并且我的判断条件是对的,我执行!");
}

else
{
Console.WriteLine("如果上面都没被执行了,我会被执行!");
}

Switch语句

注: case标签必须是具有唯一性的,不能有两个case值相同的值。
执行过程: 首先计算表达式,根据计算结果匹配case的值,若有匹配项就执行语句,跳出switch-case。
如果所有的值都不匹配,若default后有语句,执行default后的执行语句。若default后没有语句,则跳出switch-case,什么都不执行。
从哪里开始:从第一个匹配的case开始
从哪里结束:匹配以后,遇到的第一个break结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
switch(条件表达式/变量)
{
case 1:
执行语句;//是1的话,执行
break;
case 2:
执行语句;//是2的话,执行
break;
case 3:
case 4:
执行语句;//是3或者4的话,执行
//如果没有特别需求,一定要写break结束上面的条件选择啊,不然语句宝宝就掉到其他条件选择的怀中了
break;
default:
执行语句;
break;
}

if-else if 与switch 的区别,

相同点:都可以实现多分支结构。
不同点:if-else if:可以处理范围
switch: 一般只能用于等值比较。

For循环

对特定条件进行判断,满足则执行循环体,用于将某个语句或语句块重复执行预定次数。

1
2
3
4
5
6
7
8
for(初始化;条件;增减变量)
{
循环体
}
for(int i=0; i<10; i++)
{
Console.WriteLine(i);
}

while循环

1.do-while循环体系,先执行do后面的语句块,后判断,至少执行一次语句块。在判断循环条件是否满足,满足继续循环,不满足退出循环。

1
2
3
4
5
do
{
执行语句;
}
while(条件表达式);

2.while循环 当循环条件为true时,执行循环语句继续循环,否则退出循环。循环至少一次。

1
2
3
4
5
while(判断条件)
{
语句块;
}

跳转语句

用于将控制转移给另一段代码。
包括:continue 语句、break 语句、return 语句。

Continue语句

退出本次循环,执行下次循环。

1
2
3
4
5
6
7
8
9
10
11
//计算1到100之间能被3整除的数字累加和
int sum = 0;
for (int i = 1; i <= 100; i++)
{
if (i % 3 != 0)
{
continue;跳转不能被3整除的数字
}
sum += i;
}

Break语句

退出最近的循环体或switch语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
while (true) 死循环
{
if(退出条件)
{
break; 满足跳转则退出循环
}
循环体
}
/*******************/
int a=1;
while(true)
{
if(a>3)
{
break;
}
a++;
}

Goto语句

goto语句只允许在一个语句块内跳出,或者在一个语句块内的一个地方跳到另一个地方;不允许从一个语句块外面跳入一个语句块的内部

1
2
3
4
5
6
7
8
int i = 0;
cc: Console.Write(i);
if (i < 9)
{
i++;
goto cc;
}

Day2

方法

什么是方法

各种语言都有方法的概念,有的语言成其为函数或者过程。
方法就是对一系列语句的命名,表示一个功能或者行为。
如:Start、Update、Movement……
使用方法可以提高代码的可重用性和可维护性(代码层次结构更清晰)。

其实工作就是做方法(工具)

语法

定义方法:

1
2
3
4
5
6
7
8
9
10
[访问修饰符] [可选修饰符] 返回类型 方法名称(参数列表)
{
//方法体
return 结果;
}
public static void Main(int a)
{
Console.WirteLine("我被执行了!");
}

调用方法:

方法名称(参数);

1
2
3
int a=1;
Main(a);

返回值

返回值:方法定义者告诉调用者的结果。
如果方法有返回值,方法体中必须有return语句,且返回的数据与返回值类型必须兼容。
void代表无返回值类型,方法体中return关键字可有可无。
return后面的语句将不再执行。
调用方法时,如果需要结果,声明相应类型的变量接收返回值数据。

参数列表

1.参数

方法定义者需要调用者传递的信息。
定义方法时叫形式参数,简称形参;
调用方法是叫实际参数,简称实参;
实参与形参要一一对应(类型、数量、顺序)

2.值参数
默认为值参数。
调用方法时复制实参变量所存储的内容。
作用:传递数据。
语法:
……(数据类型 参数名[,数据类型 参数名])

1
2
Main(int a)

3.引用参数
使用ref关键字修饰。
调用方法时复制实参变量在栈中的引用。
作用:改变数据。
语法:
……(ref 数据类型 参数名[,ref 数据类型 参数名])

1
2
Main(ref a);

4.输出参数
使用out关键字修饰。
调用方法时复制实参变量在栈中的引用。
作用:返回结果。
语法:
……(out 数据类型 参数名[,out 数据类型 参数名])

1
2
Main(out a);

与引用参数区别

  • ref 要求实参必须在传递前进行赋值
  • out 要求形参离开方法前必须赋值

5.TryParse
通过bool表达式配合TryParse使用,防止类型转换失败。
语法:

1
2
3
int number;
bool result = int.TryParse(“520”, out number);

方法重载
  • 两个方法名称相同,但参数列表不同。

  • 用于在不同条件下解决同一类型的问题。

  • 仅仅out与ref的区别不可以构成重载

数组

什么是数组

从Array类派生的,一组数据类型相同的变量组合。
一种空间连续的数据结构 。
元素通过索引(位置的序号)进行操作。

定义数组

语法
声明数组
数据类型[] 数组名;
初始化数组
数组名 = new 数据类型[元素总数];
初始化的元素类型与声明时的类型必须相同。
例:

1
2
3
int[] array01 = new int[5];
string[] array02 = new string[3];

初始化数组

1.初始化
数组初始化后,内存中存储该数据类型的默认值。
– 整形为 0
– 非整形为 0.0
– char为 \0
– string为 null
– bool为 false

2.初始化+赋值
1)可以在数组初始化的同时对元素进行赋值。
语法:
数据类型[] 数组名=new 数据类型[]{元素1,元素2};
例如:

1
2
3
int[] array01 = new int[]{ 1,2,3,4,5 };
string[] array02 = new string[] {“a”, “b”, “c”};

初始化时[]内也可以填入数组长度,但必须与所赋值的元素总数一致。
例如:

1
2
double[] array03 = new double[2]{ 1.0, 2.0 }; 

2)可以在数组声明的同时对元素进行赋值。
语法:
数据类型[] 数组名= {元素1,元素2};
例如:

1
2
int[] array01 = { 1,2,3,4,5 };

元素个数即为数组长度。
程序员可以省略初始化,但编译器内部仍然会”new 数据类型[]” 。
不支持以下写法:

1
2
3
double[] array03;
array03 ={ 1.0, 2.0 };

访问数组元素

通过索引访问
可以通过数组的索引(位置的序号)进行读写操作。
语法:
数组名[索引]
例如:

1
2
3
4
string[] array = new string[] {“a”, “b”, “c”};
Console.WriteLine(array[0]); – 获取数组第一个元素
Console.WriteLine(array[2]); – 获取数组第三个元素

通过for遍历
遍历:按照某种顺序访问每一个元素。
for 循环遍历数组元素,正序输出到控制台中:

1
2
3
4
5
6
string[] array = new string[] { “a”, “b”, “c” };
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine( array[i] );
}

通过for遍历(2)
for 循环遍历数组元素,倒序输出到控制台中:

1
2
3
4
5
6
string[] array = new string[] { “a”, “b”, “c” };
for (int i = array.Length - 1; i >= 0; i–)
{
Console.WriteLine( array[i] );
}

通过foreach遍历
foreach 是一种更简单更明了的读取数组元素的语句。
局限性:
– 只能读取全部元素(语句本身)
– 不能修改元素
– 只能遍历实现Ienumerable接口的集合对象
语法:

1
2
3
4
5
foreach(元素类型 变量名 in 数组名)
{
变量名表示数组中的每个元素
}

通过 foreach 遍历(2)
foreach 循环遍历数组元素,输出到控制台中:

1
2
3
4
5
6
string[] array = new string[] { “a”, “b”, “c” };
foreach (string item in array)
{
Console.WriteLine( item );
}

常用方法及属性

数组长度:数组名.Length
清除元素值:Array.Clear
复制元素: Array.copy 数组名.CopyTo
克隆:数组名.Clone
查找元素: Array.IndexOf Array.LastIndexOf
排序: Array.Sort
反转: Array.Reverse

数组的分类
  • 一维数组
1
2
int [] a={};

  • 多维数组

    具有两个或多个索引的数组

    语法:
    – 声明 + 初始化

    1
    2
    3
    数据类型[,] 数组名 = new 数据类型[行数,列数];
    string[,] array01 = new string[3,2];

    – 初始化 + 赋值

    1
    2
    3
    数组名 = new 数据类型[,]{ {元素1,元素2}, {元素3,元素4} };
    int[,] array02 = new int[,]{ {1,2},{3,4} };

    – 读写元素

    1
    2
    数组名[行索引,列索引] 

交错数组

元素为数组的数组,每个元素都是一个新的一位数组。

语法:

– 定义

1
2
3
数据类型[][] 数组名 = new 数据类型[ 元素总数 ] [];
string[][] array = new string[3] [];

– 赋值

1
2
3
数组名[索引] = new 数据类型[子元素数];
array[0] = new string[2];

– 读写元素

1
2
数组名[元素索引][子元素索引]

参数数组

在方法形参中通过关键字params定义。
方法调用者可以传递数组,也可以传递一组数据类型相同的变量,甚至可以不传递参数。

注意:
参数数组必须在形参列表中的最后一位。
只能在一维数组上使用params关键字。
WriteLine中使用占位符,就是通过参数数组实现的。
例:定义整数相加的方法

1
2
3
4
5
6
7
8
private static int Add( params int[] array )
{
int sum = 0;
foreach (int item in array)
sum += item;
return sum;
}

数据类型

类型分类

通用类型系统CTS(Common Type System)是.NET框架中的一个组成部分,为所有面向.NET框架的语言定义了数据类型的规则。

  • 值类型:存储数据本身。
  • 引用类型:存储数据的引用(内存地址)
类型归属

局部变量

定义在方法内部的变量。

特点:

– 没有默认值,必须自行设定初始值,否则不能使用。
– 方法被调用时,存在栈中,方法调用结束时从栈中清除。
值类型与引用类型
值类型:
声明在栈中,数据存储在栈中。
引用类型:
声明在栈中,数据存储在堆中,栈中存储该数据的引用。

成员变量

定义在类中方法外的变量

特点:

– 具有默认值。
– 所在类被实例化后,存在堆中,对象被回收时,成员变量从堆中清除。
– 可以与局部变量重名

值类型与引用类型
值类型:
声明在堆中,数据存储在堆中。
引用类型:
声明在堆中,数据存储在堆的另一块空间。

拆装箱

装箱Box

值类型隐式转换为 object 类型或由此值类型实现的任何接口类型的过程。
内部机制:
1.在堆中开辟内存空间
2.将值类型的数据复制到堆中
3.返回堆中新分配对象的地址

拆箱 unBox

从 object 类型到值类型或从接口类型到实现该接口的值类型的显式转换。
内部机制:
1.判断给定类型是否是装箱时的类型
2.返回已装箱实例中属于原值类型字段的地址

注意

拆箱后的类型必须与装箱时的类型相同。
伴随拆箱的字段复制步骤不属于拆箱过程。
装箱和拆箱不是互逆的过程,装箱的性能开销远大于拆箱。

String类

特性

字符串常量具备字符串池特性
字符串常量在创建前,首先在字符串池中查找是否存在相同文本。如果存在,则直接返回该对象引用;如果不存在,则开辟空间存储。
目的:提高内存利用率。

字符串具有不可变性

字符串常量一旦进入内存,就不得再次改变。因为如果在原位置改变会使其他对象内存被破坏,导致内存泄漏。当遇到字符串变量引用新值时,会在内存中新建一个字符串,将该字符串地址交由该变量引用。

垃圾回收器

GC(Garbage Collection)是CLR中一种针对托管堆自动回收释放内存的服务。
GC线程从栈中的引用开始跟踪,从而判定哪些内存是正在使用的,若GC无法跟踪到某一块堆内存,那么就认为这块内存不再使用了,即为可回收的。

Day3

类和对象

什么是类和对象

面向对象:是一种软件开发的思想,用于指导程序员如何用人的思维方式对软件进行分析、设计与编程。

  • 类是一个抽象的概念,即为生活中的”类别”。
  • 对象是类的具体实例,即归属于某个类别的”个体”。

例如:学生是一个类,表示一种类型,”八戒同学”则是一个对象。
名词类型的状态,作为数据成员。
动词类型的行为,作为方法成员。

创建类

语法:

1
2
3
4
5
6
7
8
9
访问级别 class 类名
{
类成员……
}
private class MyClass
{

}

通常每个类都在一个独立的c#源文件中。
创建新的类意味着在当前项目中产生了一种新的数据类型。

创建对象

语法:

1
2
3
4
//类名 引用名;
//引用名 = new 构造函数(参数列表);
MyClass myclass = new MyClass();

创建对象的过程也称为”实例化”,

访问修饰符

用于修饰类及类成员的访问可见范围。

  • public:所属类的成员以及非所属类的成员都可以访问。
  • private:只有所属类的成员才能访问。[类成员的默认级别]

属性

对字段起保护作用,可实现只读、只写功能。
本质就是对字段的读取与写入方法。

语法:

1
2
3
4
5
6
7
8
9
10
11
[访问修饰符] 数据类型 属性名
{
get { return 字段; }
set { 字段 = value; }
}
public int A
{
get{return this.value;}
set{this.value = value}
}

  • 通常一个公有属性和一个私有字段对应。
  • 属性只是外壳,实际上操作的私有字段。

自动属性

当属性访问器中不需要任何其他逻辑时,使用自动属性可以更加简洁。
本质就是一个字段两个方法。

语法:

1
2
3
[访问修饰符] 数据类型 属性名 { get ; set ; } 
public int A{ get ; set ; }

构造函数

提供了创建对象的方式,初始化类数据成员的特殊方法。

语法:

1
2
3
4
5
6
7
8
9
//[访问修饰符] 类名([参数列表])
//{
//初始化……
//}
public Myclass(int a)
{
//初始化……
}

特点

  • 与类同名。
  • 没有返回值,也不能写void。
  • 不能被直接调用,必须通过new运算符在创建对象时才会自动调用。
  • 每个类都必须至少有一个构造函数,若不提供,编译器自动生成一个无参构造函数。
  • 如果程序员定义了构造函数,则编译器不会再提供。

this关键字

  • 表示当前对象的引用。
  • 访问当前类成员时,使用this关键字,可以提高代码的可读性;在没有歧义的情况下,也可以省略。

类结构

1
2
3
4
5
6
7
8
访问级别 class 类名
{
字段:存储数据
属性:保护字段
构造函数:提供创建对象的方式,初始化类的数据成员
方法:向类的外部提供某种功能
}

Static

  • 使用static关键字修饰的成员变量。
  • 静态成员变量属于类,类被加载时初始化,且只有一份。
  • 实例成员变量属于对象,在每个对象被创建时初始化,每个对象一份。

特点:

存在优先于对象,被所有对象所共享,常驻内存

静态构造函数

  • 初始化类的静态数据成员。
  • 仅在类被加载时执行一次。
  • 不允许使用访问修饰符。

静态方法

  • 通过引用调用实例方法时,会隐式的传递对象引用,以便在方法内部可以正确访问该对象成员变量。
  • 通过类名调用静态方法时,因为没有具体对象,所以在static方法中不能访问实例成员。

静态类

  • 使用static关键字修饰的类。
  • 不能实例化,只能包含静态成员。
  • 静态类不能被继承,但是静态方法、属性都可以被继承。

适用性

  • 利:单独空间存储,所有对象共享,可直接被类名调用。
  • 弊:静态方法中只能访问静态成员,共享数据被多个对象访问会出现并发。

适用场合:

1.所有对象需要共享的数据。
2.在没有对象前就要访问成员。
3.工具类适合做静态类(常用,不需要过多数据)。

结构

什么是结构

定义:用于封装小型相关变量的值类型。与类语法相似,都可以包含数据成员和方法成员。但结构属于值类型,类属于引用类型。

适用性:

表示点、颜色等轻量级对象。如创建存储1000个点的数组,如果使用类,将为每个对象分配更多内存,使用结构可以节约资源。

定义结构

  • 使用 struct 关键字定义。
  • 除非字段被声明为 const 或 static,否则无法初始化。
  • 结构不能继承,但可以实现接口。

构造函数

  • 结构总会包含无参数构造函数。
  • 构造函数中必须初始化所有字段。

枚举

枚举

列举某种数据的所有取值。

作用:

增强代码的可读性,限定取值。

语法:

1
2
3
enum 名字{值1,值2,值3,值4}
enum A{1,2,3,4}

  • 枚举元素默认为int,准许使用的枚举类型有byte、sbyte、short、ushort、int、uint、long或ulong。
  • 每个枚举元素都是有枚举值。默认情况下,第一个枚举的值为0,后面每个枚举的值一次递增1,可以修改值,后面枚举数的值依次递增。

标志枚举

可以同时赋多个枚举值。

条件:

– 任意两个枚举值做按位或运算的结果不能与其他枚举值相同。
– 使用 [Flags] 特性标记枚举类型。
标志枚举(续1)

语法:

1
2
3
4
5
6
7
8
9
10
11
[Flags]
enum 枚举类型名称
{
枚举值1 = 1,
枚举值2 = 2,
枚举值3 = 4,
枚举值4 = 8,
枚举值4 = 16,
……
}

数据类型转换

1
2
3
Enum --> int
int 变量名 =(int)枚举值;

1
2
3
int --> Enum
枚举类型 变量名 =(枚举类型)整数;

数据类型转换(续1)

1
2
3
Enum --> string
string 变量名 = 枚举值.ToString();

1
2
3
4
string -->  Enum 
枚举类型 变量名 =
(枚举类型)Enum.Parse(typeof(枚举类型 ), "枚举值");