部分是转载
枚举、结构体、数组和集合
一、值类型
C#支持两种值类型:枚举和结构
1.1 枚举(enum)
1)和所有值类型一样,枚举可以使用?修饰符来创建一个可空的枚举变量,如:Season? colorful=null;
2)可以指定枚举的类型,如:
enum Season{spring=1,summer,fall,winter}可以,也可以像下面这样声明:
enum Season:short{spring,summer,fall,winter}
一种枚举看可以基于8种整数类型的任何一种:byte,sbyte,short,ushort,int,uint,long或者ulong
1.2 结构(Struct)——结构体和类的区别
什么是结构体
struct Point //被struct修饰的叫做结构 结构体
使用结构要注意的地方
1、类里面可以定:成员变量 方法 属性 构造函数
2、结构里可以定义字段 还可以定义属性 还可以定义方法 还可以构造函数.
3、结构里的字段声明的时候 不能给初始值
4、声明结构对象的时候 如果不通过new关键字来声明 那么这个结构对象的字段没有默认值。
5、声明结构对象的时候 如果通过了new关键字来声明 那么这个结构对象的字段就有默认值
6、字段有默认值 值类型的默认值是0 引用类型默认值是null
7、无论怎么样,结构体都会有无参数的构造函数...
8、结构不能从类或其他结构继承。
结构与雷的区别
1)结构体是值类型,而类是引用类型
2)结构体的实例称为值,存储在栈上,而类的实例称为对象,存储在堆上
3)结构体不能为结构声明默认构造函数,而类可以;但是,如果没有写构造函数,结构体和类一样会有一个默认的构造函数,只是结构体不能显示地为自己写默认构造函数
4)结构体即使自己声明了构造函数,编译器还是会为其生成默认构造函数,而类则不会;
5)在类中,声明变量(实例字段)的同时,就可以初始化它,而结构体不可以,它必须在函数里面初始化
6)结构体的构造器如果不初始化字段,编译器是不会帮助其初始化的,而类则可以
隐式的构造函数 做了什么事情:
1、给所有的字段 值类型的字段赋值为0 引用类型 赋值为null
2、如果程序员为这个结构定义了构造函数 那么就要求程序员要在这个构造函数中
为所有的字段赋值
3、在结构的构造函数中不能通过属性为字段赋值
结构体 是值类型
什么时候用类,什么时候用结构体
1、当封装的内容比较少的时候 就适合用结构
2、封装的内容比较多的时候 就适合用类
3、传值的效果 如果想传递拷贝 就定义为结构 如果想传值引用 就定义为类
二、数组和集合
2.1 数组变量
1)初始化数组 int [] pins=new int[4] {9,3,7,2};
初始化数组时,实际上可以省略new表达式和数组的大小,如:
int [] pins={9,3,2,7};
2)创建隐式类型的数组
如果在声明数组的时候指定了一个初始值列表,就可以让C#编译器自己推断数组中的元素的类型,如下所示:
var names=new[]{"John","Dim","Rose"};
首先,我们省略了类型后的方括号,本例中的names变量被声明为var,而不是var[];其次,必须在初始值列表之前添加new[]。注意:使用这个语法,必须保证所有初始值都有相同的类型。
3)复制数组
i)
int[] pins={9,7,3,2};
int[] alias=pins;//pins 和alias引用同一个数组实例
这里,pins改变了,alias也会跟着改变,所以,不是真正物理上的拷贝,只是引用相同
ii)如果想要真正复制一个数组实例,获得堆上实际数据的副本,那么必须做两件事:其一、必须创建类型和大小与原始数组相同的一个新的数组实例;其二,将数据元素逐个复制到新数组
iii)用CopyTo方法,将一个数组复制到另一个数组,并从指定的位置开始
iv)用Copy,从0下标开始复制,并要指定复制长度
2.2 集合
集合有很多种类型,熟悉的有ArrayList、Stack、Queue;目前还较为生疏的有:Hashtable、SortedList。
Hashtable和SortedList是关联数组,在用的时候,要将键值和映射的目标值一起成对存入。以Hashtable为例:
1)Hashtable不能有重复的key值,如果调用add来添加一个已有的key,就会抛出异常,如果使用方括号表示法来添加一个key/Value对(下例就是这样),就不会抛异常;
2)使用foreach语句遍历一个Hashtable时,会返回一个DictionaryEntry。DictionaryEntry类允许通过Key属性和Value属性来访问两个object数组中的key和value元素;
Hashtable ages=new Hashtable();
ages["John"]=44;
ages["Dim"]=20;
ages["Tim"]=50;
SortedList和Hashtable一样,只是keys数组总是排好序的。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 结构 7 { 8 struct Point //被struct修饰的叫做结构 结构体 9 { 10 //类里面可以定:成员变量 方法 属性 构造函数 11 public int x; 12 13 #region 测试代码 14 //public int X 15 //{ 16 // get { return x; } 17 // set { x = value; } 18 //} 19 //private int y; 20 //public void SayHi() 21 //{ 22 // Console.WriteLine("大家好,才是真的好!"); 23 //} 24 //public Ponit(int x,int y) 25 //{ 26 // this.x = x; 27 // this.y = y; 28 //} 29 #endregion 30 public int y; 31 public Person p; 32 //结构里可以定义字段 还可以定义属性 还可以定义方法 还可以构造函数. 33 //结构里的字段声明的时候 不能给初始值 34 35 //声明结构对象的时候 如果不通过new关键字来声明 那么这个结构对象的字段没有默认值。 36 //声明结构对象的时候 如果通过了new关键字来声明 那么这个结构对象的字段就有默认值 37 //字段有默认值 值类型的默认值是0 引用类型默认值是null 38 39 //无论怎么样,结构体都会有无参数的构造函数... 40 //隐式的构造函数 做了什么事情: 41 //给所有的字段 值类型的字段赋值为0 引用类型 赋值为null 42 43 //如果程序员为这个结构定义了构造函数 那么就要求程序员要在这个构造函数中 44 //为所有的字段赋值 45 //在结构的构造函数中不能通过属性为字段赋值 46 47 //结构体 是值类型 48 49 50 //什么时候用类 什么时候用结构 51 // 当封装的内容比较少的时候 就适合用结构 52 // 封装的内容比较多的时候 就适合用类 53 // 传值的效果 如果想传递拷贝 就定义为结构 如果想传值引用 就定义为类 54 55 56 public Point(int x,int y) 57 { 58 this.x = x; 59 this.y = y; 60 this.p = null; 61 } 62 public void Test(int x) 63 { 64 this.X = x; 65 } 66 67 public int X 68 { 69 get 70 { 71 return this.x; 72 } 73 set 74 { 75 this.x = value; 76 } 77 } 78 79 80 } 81 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 结构 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 //声明结构对象的语法之一 13 // 14 //Console.WriteLine(p.x); 15 //Console.WriteLine(p.y); 16 //Console.WriteLine(p.p); 17 //Person p; 18 //p.Test(); 19 //声明结构对象的时候 如果不通过new关键字来声明 那么这个结构对象的字段没有默认值。 20 //Ponit p = new Ponit(); 21 //Ponit p1; 22 //Console.WriteLine(p.x); 23 24 //Point p = new Point(); 25 //Console.WriteLine(p.x); 26 //Point p1; 27 //p1.x = 12; 28 //p1.y = 11; 29 //Console.WriteLine(p1.y); 30 //Point p = new Point(1,2); 31 //p.Test(190); 32 //Console.WriteLine(p.X); 33 34 //Point p = new Point(12,14); 35 //Point p1 = p; 36 //p1.x = 15; 37 //p1.y = 29; 38 //Console.WriteLine(p.x+":"+p.y); 39 Rectangle r = new Rectangle(); 40 r.height = 120; 41 r.width = 190; 42 Console.WriteLine(r.GetZhouChang()); 43 Console.ReadKey(); 44 } 45 } 46 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 枚举 7 { 8 enum Direction:byte//用enum关键字 后面跟上枚举的名称 9 { 10 //枚举的成员 成员之间用逗号分隔. 11 //枚举里只能定义枚举的成员.. 12 //枚举的成员的值直接写就可以了,不需要再去用字符串形式 13 //枚举成员的命名规则同样要遵守变量的命名规则 14 //枚举的作用,限定取值范围. 15 //每1个枚举成员都对应了1个整型的数字 默认从0开始 依次递增 16 //如何将枚举值转换为对应的整数值 17 // Direction dir = Direction.South; 18 // int i = (int)dir; 19 // 将1个整型的数字转换为 这个数字所代表的枚举值 20 //Direction dir1 = (Direction)1; 21 // Console.WriteLine(dir1); 22 // 如果整数所代表的枚举值不存在,则转换结果为这个整数本身. 23 24 //可以手动的为枚举的成员指定所对应的整型数字 25 //如果某些枚举值指定了所对应的整型数字 而后面的没有指定 26 //那么后面的会在前面的基础上递增 27 East = 4, South = 1, West = 2, North = 3 28 //全部枚举成员所代表的整数一致: 29 // 那么取的中间的枚举项 /2 30 //枚举成员所代表的数值只能是 整型的. 31 //byte int long sbyte short 32 //如果没有特定的说明 那么就是int类型的 33 //更改枚举值所对应的整型的类型 34 // 在枚举名称后面写上: 整数的数据类型 35 } 36 /// <summary> 37 /// 人类 38 /// </summary> 39 class Person 40 { 41 bool gender; 42 public bool Gender 43 { 44 get { return gender; } 45 set { gender = value; } 46 } 47 public Direction dir;//声明枚举类型的变量 48 49 public int 年龄 { get; set; } 50 } 51 class Program 52 { 53 54 55 static void Main(string[] args) 56 { 57 Direction dir; 58 //Direction dir = Direction.West; 59 //int i = (int)dir; 60 //Direction dir1 = (Direction)13; 61 //Console.WriteLine(dir1); 62 //int max = int.MaxValue; 63 // Person p = new Person(); 64 // string str = "east"; 65 //将字符串转换为枚举变量 66 //区分大小写转换 67 //Direction dir = (Direction)Enum.Parse(typeof(Direction), str); 68 //忽略大小写转换 69 // Direction dir1 = (Direction)Enum.Parse(typeof(Direction), str,true); 70 //如何将1个枚举变量转换为1个字符串? 71 //string s = dir1.ToString(); 72 // Console.WriteLine(dir1); 73 //直接将枚举值转换为枚举值所对应的数值的字符串形式 74 // int i = (int)Direction.East; 75 // i.ToString(); 76 //Direction dir2 = Direction.East; 77 //string s2= dir2.ToString("d"); 78 //枚举是1个值类型 79 //Direction dir = Direction.East; 80 //Direction dir1 = dir; 81 //dir1 = Direction.North; 82 //Console.WriteLine(dir); 83 //枚举值的默认值是0 也就是0代表的枚举项 84 //Console.WriteLine(dir); 85 86 Console.ReadKey(); 87 } 88 } 89 enum State 90 { 91 在线, 离线, 忙碌, 吃饭 92 } 93 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 数组 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 13 // //for (int i = 0; i < arr.Length; i++) 14 // //{ 15 // // arr1[i] = arr[i]; 16 // //} 17 // //数组拷贝 18 // //arr.CopyTo(arr1, 0); 19 // //Array.Copy(arr, arr1, arr.Length); 20 // int[] arr = new int[4] { 12, 23, 4, 6 }; 21 // int[] arr1 = new int[10]; 22 //// Buffer.BlockCopy(arr, 0, arr1, 0, arr.Length); 23 // foreach (int i in arr1) 24 // { 25 // Console.WriteLine(i); 26 // } 27 28 // Test2Arrar(); 29 // TestDuoWei(); 30 //TestJiaoCuoArray(); 31 TestTest(); 32 Console.ReadKey(); 33 34 } 35 36 /// <summary> 37 /// 二维数组 38 /// </summary> 39 static void Test2Arrar() 40 { 41 int[,] arr = new int[4, 5]; 42 arr[0, 0] = 12; 43 arr[1, 2] = 19; 44 #region MyRegion 45 //Console.WriteLine(arr[0, 0]); 46 //遍历 47 Console.WriteLine("*********************"); 48 // Console.WriteLine(arr.Length); 49 //arr.Length表示二维数组的元素的个数.... 行*列 50 //for (int i = 0; i < 2; i++) 51 //{ 52 // for (int j = 0; j < 3; j++) 53 // { 54 // Console.WriteLine(arr[i,j]); 55 // } 56 //} 57 //int[] arr1 = new int[2]; 58 //int rank = arr.Rank;//得到数组的维度 59 //Console.WriteLine(rank); 60 // arr.Rank;得到的是维度 如果这个数组是1个2维数组 永远得到的是2 61 ////遍历二维数组的方式 62 //for (int i = 0; i < arr.Rank; i++) 63 //{ 64 // for (int j = 0; j < arr.Length / arr.Rank; j++) 65 // { 66 // Console.WriteLine(arr[i, j]); 67 // } 68 //} 69 #endregion 70 71 Console.WriteLine("*****************************"); 72 73 //int length = arr.GetLength(1);//得到二维数组的行数0或者列数1 74 //for (int i = 0; i < arr.GetLength(0); i++) 75 //{ 76 // for (int j = 0; j < arr.GetLength(1); j++) 77 // { 78 // Console.WriteLine(arr[i,j]); 79 // } 80 //} 81 } 82 83 static void TestDuoWei() 84 { 85 int[, ,] arr = new int[3, 2, 4]; 86 arr[0, 0, 0] = 112; 87 Console.WriteLine(arr[0, 0, 0]); 88 for (int i = 0; i < arr.GetLength(0); i++) 89 { 90 for (int j = 0; j < arr.GetLength(1); j++) 91 { 92 for (int k = 0; k < arr.GetLength(2); k++) 93 { 94 Console.WriteLine(arr[i, j, k]); 95 } 96 } 97 } 98 Console.WriteLine("**********************"); 99 Console.WriteLine(arr.Length); 100 Console.WriteLine(arr.Rank); 101 Console.WriteLine(arr.GetValue(0, 0, 0)); 102 } 103 104 105 static void TestJiaoCuoArray() 106 { 107 ////长度不可变 数组一旦声明 长度不可改变 108 ////交错数组的本质就是1个一维数组 只不过这个一维数组的元素又是1个数组 109 //int[][] arr = new int[3][]; 110 //arr[0] = new int[] { 1, 2, 34 }; 111 //arr[1] = new int[] { 1, 2, 3 }; 112 //arr[2] = new int[] { 4, 5, 6,5,6,7,8,89,9 }; 113 ////arr的第1个元素的第1个元素赋值 114 //arr[0][0] = 119; 115 ////Console.WriteLine(arr[0][0]); 116 //for (int i = 0; i < arr.Length; i++) 117 //{ 118 // for (int j = 0; j < arr[i].Length; j++) 119 // { 120 // Console.WriteLine(arr[i][j]); 121 // } 122 //} 123 int[][][][] arr = new int[3][][][]; 124 125 //二维数组 //交错数组 126 127 128 } 129 130 131 static void TestArray() 132 { 133 int[] arrs = { 1, 2, 3, 4, 5 }; 134 int[,] arr = { { 1, 2, 3 }, { 4, 5, 5 } }; 135 int[][] jiaocuoArray = { new int[] { 1, 2, 3 }, new int[] { 4, 5, 6, 7, 8, 9 } }; 136 137 } 138 139 140 static void TestTest() 141 { 142 //int[] arr = { 1,2,3,4,5}; 143 //int arr = 12; 144 // int[][] arr = new int[2][]; 145 int[,] arr = new int[2,3]; 146 bool b = arr is int[,]; 147 Console.WriteLine(b); 148 } 149 } 150 }