前言👻
前面几篇博客介绍了C#的一些基础知识,包括基本语法、数据类型、运算符等。在本篇博客就来介绍在C#中最常用的几种数据类型——数组、字符串、结构体、枚举、类
数组(Array)💚
数组是一个存储相同类型元素的固定大小的顺序集合。数组是用来存储数据的集合,通常认为数组是一个同一类型变量的集合。
声明数组变量并不是声明 number0、number1、…、number99 一个个单独的变量,而是声明一个就像 numbers 这样的变量,然后使用 numbers[0]、numbers[1]、…、numbers[99] 来表示一个个单独的变量。数组中某个指定的元素是通过索引来访问的。
所有的数组都是由连续的内存位置组成的。最低的地址对应第一个元素,最高的地址对应最后一个元素。
声明数组
在 C# 中声明一个数组,您可以使用下面的语法:
datatype[] arrayName;
其中,
- datatype 用于指定被存储在数组中的元素的类型。
- [ ]指定数组的秩(维度)。秩指定数组的大小。
- arrayName 指定数组的名称。
例如:
double[] balance;
初始化数组
声明一个数组不会在内存中初始化数组。当初始化数组变量时,您可以赋值给数组。
数组是一个引用类型,所以您需要使用 new 关键字来创建数组的实例。
例如:
double[] balance = new double[10];
赋值给数组
可以通过使用索引号赋值给一个单独的数组元素,比如:
double[] balance = new double[10]; balance[0] = 4500.0;
可以在声明数组的同时给数组赋值,比如:
double[] balance = { 2340.0, 4523.69, 3421.0};
也可以创建并初始化一个数组,比如:
int [] marks = new int[5] { 99, 98, 92, 97, 95};
在上述情况下,你也可以省略数组的大小,比如:
int [] marks = new int[] { 99, 98, 92, 97, 95};
也可以赋值一个数组变量到另一个目标数组变量中。在这种情况下,目标和源会指向相同的内存位置:
int [] marks = new int[] { 99, 98, 92, 97, 95}; int[] score = marks;
当创建一个数组时,C# 编译器会根据数组类型隐式初始化每个数组元素为一个默认值。例如,int 数组的所有元素都会被初始化为 0。
访问数组元素
元素是通过带索引的数组名称来访问的。这是通过把元素的索引放置在数组名称后的方括号中来实现的。例如:
double salary = balance[9];
下面是一个实例,使用上面提到的三个概念,即声明、赋值、访问数组:
实例 using System; namespace ArrayApplication { class MyArray { static void Main(string[] args) { int [] n = new int[10]; /* n 是一个带有 10 个整数的数组 */ int i,j; /* 初始化数组 n 中的元素 */ for ( i = 0; i < 10; i++ ) { n[ i ] = i + 100; } /* 输出每个数组元素的值 */ for (j = 0; j < 10; j++ ) { Console.WriteLine("Element[{0}] = {1}", j, n[j]); } Console.ReadKey(); } } }
当上面的代码被编译和执行时,它会产生下列结果:
Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109
使用 foreach 循环
在前面的实例中,我们使用一个 for 循环来访问每个数组元素。也可以使用一个 foreach 语句来遍历数组。
实例 using System; namespace ArrayApplication { class MyArray { static void Main(string[] args) { int [] n = new int[10]; /* n 是一个带有 10 个整数的数组 */ /* 初始化数组 n 中的元素 */ for ( int i = 0; i < 10; i++ ) { n[i] = i + 100; } /* 输出每个数组元素的值 */ foreach (int j in n ) { int i = j-100; Console.WriteLine("Element[{0}] = {1}", i, j); } Console.ReadKey(); } } }
当上面的代码被编译和执行时,它会产生下列结果:
Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109
C# 数组细节
在 C# 中,数组是非常重要的,且需要了解更多的细节。下面列出了 C# 程序员必须清楚的一些与数组相关的重要概念:
C# 字符串(String)💜
在 C# 中,您可以使用字符数组来表示字符串,但是,更常见的做法是使用 string 关键字来声明一个字符串变量。string 关键字是 System.String 类的别名。
创建 String 对象
可以使用以下方法之一来创建 string 对象:
通过给 String 变量指定一个字符串
通过使用 String 类构造函数
通过使用字符串串联运算符( + )
通过检索属性或调用一个返回字符串的方法
通过格式化方法来转换一个值或对象为它的字符串表示形式
实例 using System; namespace StringApplication { class Program { static void Main(string[] args) { //字符串,字符串连接 string fname, lname; fname = "Rowan"; lname = "Atkinson"; string fullname = fname + lname; Console.WriteLine("Full Name: {0}", fullname); //通过使用 string 构造函数 char[] letters = { 'H', 'e', 'l', 'l','o' }; string greetings = new string(letters); Console.WriteLine("Greetings: {0}", greetings); //方法返回字符串 string[] sarray = { "Hello", "From", "Tutorials", "Point" }; string message = String.Join(" ", sarray); Console.WriteLine("Message: {0}", message); //用于转化值的格式化方法 DateTime waiting = new DateTime(2012, 10, 10, 17, 58, 1); string chat = String.Format("Message sent at {0:t} on {0:D}", waiting); Console.WriteLine("Message: {0}", chat); Console.ReadKey() ; } } }
当上面的代码被编译和执行时,它会产生下列结果:
Full Name: RowanAtkinson
Greetings: Hello Message: Hello
From Tutorials Point
Message: Message sent at 17:58 on Wednesday, 10 October 2012
String 类的属性
String 类有以下两个属性:
String 类的方法
String 类有许多方法用于 string 对象的操作。下面的表格提供了一些最常用的方法:
上面的方法列表并不详尽,请访问 MSDN 库,查看完整的方法列表和 String 类构造函数。
实例
下面的实例演示了上面提到的一些方法:
比较字符串
实例 using System; namespace StringApplication { class StringProg { static void Main(string[] args) { string str1 = "This is test"; string str2 = "This is text"; if (String.Compare(str1, str2) == 0) { Console.WriteLine(str1 + " and " + str2 + " are equal."); } else { Console.WriteLine(str1 + " and " + str2 + " are not equal."); } Console.ReadKey() ; } } }
当上面的代码被编译和执行时,它会产生下列结果:
This is test and This is text are not equal.
字符串包含字符串:
实例 using System; namespace StringApplication { class StringProg { static void Main(string[] args) { string str = "This is test"; if (str.Contains("test")) { Console.WriteLine("The sequence 'test' was found."); } Console.ReadKey() ; } } }
当上面的代码被编译和执行时,它会产生下列结果:
The sequence ‘test’ was found.
获取子字符串:
实例 using System; namespace StringApplication { class StringProg { static void Main(string[] args) { string str = "Last night I dreamt of San Pedro"; Console.WriteLine(str); string substr = str.Substring(23); Console.WriteLine(substr); Console.ReadKey() ; } } }
当上面的代码被编译和执行时,它会产生下列结果:
Last night I dreamt of San Pedro
San Pedro
连接字符串:
实例 using System; namespace StringApplication { class StringProg { static void Main(string[] args) { string[] starray = new string[]{"Down the way nights are dark", "And the sun shines daily on the mountain top", "I took a trip on a sailing ship", "And when I reached Jamaica", "I made a stop"}; string str = String.Join("\n", starray); Console.WriteLine(str); Console.ReadKey() ; } } }
当上面的代码被编译和执行时,它会产生下列结果:
Down the way nights are dark
And the sun shines daily on the mountain top
I took a trip on a sailing ship
And when I reached Jamaica
I made a stop
结构体(Struct)💙
在 C# 中,结构体是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。struct 关键字用于创建结构体。
结构体是用来代表一个记录。假设您想跟踪图书馆中书的动态。您可能想跟踪每本书的以下属性:
Title
Author
Subject
Book ID
定义结构体
为了定义一个结构体,您必须使用 struct 语句。struct 语句为程序定义了一个带有多个成员的新的数据类型。
例如,可以按照如下的方式声明 Book 结构:
struct Books { public string title; public string author; public string subject; public int book_id; };
下面的程序演示了结构的用法:
实例 using System; using System.Text; struct Books { public string title; public string author; public string subject; public int book_id; }; public class testStructure { public static void Main(string[] args) { Books Book1; /* 声明 Book1,类型为 Books */ Books Book2; /* 声明 Book2,类型为 Books */ /* book 1 详述 */ Book1.title = "C Programming"; Book1.author = "Nuha Ali"; Book1.subject = "C Programming Tutorial"; Book1.book_id = 6495407; /* book 2 详述 */ Book2.title = "Telecom Billing"; Book2.author = "Zara Ali"; Book2.subject = "Telecom Billing Tutorial"; Book2.book_id = 6495700; /* 打印 Book1 信息 */ Console.WriteLine( "Book 1 title : {0}", Book1.title); Console.WriteLine("Book 1 author : {0}", Book1.author); Console.WriteLine("Book 1 subject : {0}", Book1.subject); Console.WriteLine("Book 1 book_id :{0}", Book1.book_id); /* 打印 Book2 信息 */ Console.WriteLine("Book 2 title : {0}", Book2.title); Console.WriteLine("Book 2 author : {0}", Book2.author); Console.WriteLine("Book 2 subject : {0}", Book2.subject); Console.WriteLine("Book 2 book_id : {0}", Book2.book_id); Console.ReadKey(); } }
当上面的代码被编译和执行时,它会产生下列结果:
Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject :
C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom
Billing Book 2 author : Zara Ali
Book 2 subject : Telecom Billing
Tutorial Book 2 book_id : 6495700
C# 结构的特点
已经用了一个简单的名为 Books 的结构。在 C# 中的结构与传统的 C 或 C++ 中的结构不同。C# 中的结构有以下特点:
结构可带有方法、字段、索引、属性、运算符方法和事件。
结构可定义构造函数,但不能定义析构函数。但是,您不能为结构定义无参构造函数。无参构造函数(默认)是自动定义的,且不能被改变。
与类不同,结构不能继承其他的结构或类。
结构不能作为其他结构或类的基础结构。
结构可实现一个或多个接口。
结构成员不能指定为 abstract、virtual 或 protected。
当您使用 New 操作符创建一个结构对象时,会调用适当的构造函数来创建结构。与类不同,结构可以不使用 New 操作符即可被实例化。
如果不使用 New 操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使用。
类 vs 结构
类和结构有以下几个基本的不同点:
类是引用类型,结构是值类型。
结构不支持继承。
结构不能声明默认的构造函数。
针对上述讨论,让我们重写前面的实例:
实例 using System; using System.Text; struct Books { private string title; private string author; private string subject; private int book_id; public void setValues(string t, string a, string s, int id) { title = t; author = a; subject = s; book_id =id; } public void display() { Console.WriteLine("Title : {0}", title); Console.WriteLine("Author : {0}", author); Console.WriteLine("Subject : {0}", subject); Console.WriteLine("Book_id :{0}", book_id); } }; public class testStructure { public static void Main(string[] args) { Books Book1 = new Books(); /* 声明 Book1,类型为 Books */ Books Book2 = new Books(); /* 声明 Book2,类型为 Books */ /* book 1 详述 */ Book1.setValues("C Programming", "Nuha Ali", "C Programming Tutorial",6495407); /* book 2 详述 */ Book2.setValues("Telecom Billing", "Zara Ali", "Telecom Billing Tutorial", 6495700); /* 打印 Book1 信息 */ Book1.display(); /* 打印 Book2 信息 */ Book2.display(); Console.ReadKey(); } }
当上面的代码被编译和执行时,它会产生下列结果:
Title : C Programming
Author : Nuha Ali
Subject : C Programming Tutorial
Book_id : 6495407
Title : Telecom Billing
Author : Zara Ali
Subject : Telecom Billing Tutorial
Book_id : 6495700
枚举(Enum)💛
枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。
C# 枚举是值类型。换句话说,枚举包含自己的值,且不能继承或传递继承。
声明 enum 变量
声明枚举的一般语法:
enum <enum_name> { enumeration list };
其中,
- enum_name 指定枚举的类型名称。
- enumeration list 是一个用逗号分隔的标识符列表。
枚举列表中的每个符号代表一个整数值,一个比它前面的符号大的整数值。默认情况下,第一个枚举符号的值是 0.例如:
enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
实例
下面的实例演示了枚举变量的用法:
实例 using System; public class EnumTest { enum Day { Sun, Mon, Tue, Wed, Thu, Fri, Sat }; static void Main() { int x = (int)Day.Sun; int y = (int)Day.Fri; Console.WriteLine("Sun = {0}", x); Console.WriteLine("Fri = {0}", y); } }
当上面的代码被编译和执行时,它会产生下列结果:
Sun = 0
Fri = 5
类(Class)❤️
当你定义一个类时,你定义了一个数据类型的蓝图。这实际上并没有定义任何的数据,但它定义了类的名称意味着什么,也就是说,类的对象由什么组成及在这个对象上可执行什么操作。对象是类的实例。构成类的方法和变量称为类的成员。
类的定义
类的定义是以关键字 class 开始,后跟类的名称。类的主体,包含在一对花括号内。下面是类定义的一般形式:
<access specifier> class class_name { // member variables <access specifier> <data type> variable1; <access specifier> <data type> variable2; ... <access specifier> <data type> variableN; // member methods <access specifier> <return type> method1(parameter_list) { // method body } <access specifier> <return type> method2(parameter_list) { // method body } ... <access specifier> <return type> methodN(parameter_list) { // method body } }
请注意:
访问标识符 指定了对类及其成员的访问规则。如果没有指定,则使用默认的访问标识符。类的默认访问标识符是
internal,成员的默认访问标识符是 private。
数据类型 指定了变量的类型,返回类型 指定了返回的方法返回的数据类型。
如果要访问类的成员,你要使用点(.)运算符。
点运算符链接了对象的名称和成员的名称。
下面的实例说明了目前为止所讨论的概念:
实例 using System; namespace BoxApplication { class Box { public double length; // 长度 public double breadth; // 宽度 public double height; // 高度 } class Boxtester { static void Main(string[] args) { Box Box1 = new Box(); // 声明 Box1,类型为 Box Box Box2 = new Box(); // 声明 Box2,类型为 Box double volume = 0.0; // 体积 // Box1 详述 Box1.height = 5.0; Box1.length = 6.0; Box1.breadth = 7.0; // Box2 详述 Box2.height = 10.0; Box2.length = 12.0; Box2.breadth = 13.0; // Box1 的体积 volume = Box1.height * Box1.length * Box1.breadth; Console.WriteLine("Box1 的体积: {0}", volume); // Box2 的体积 volume = Box2.height * Box2.length * Box2.breadth; Console.WriteLine("Box2 的体积: {0}", volume); Console.ReadKey(); } } }
当上面的代码被编译和执行时,它会产生下列结果:
Box1 的体积: 210
Box2 的体积: 1560
成员函数和封装
类的成员函数是一个在类定义中有它的定义或原型的函数,就像其他变量一样。作为类的一个成员,它能在类的任何对象上操作,且能访问该对象的类的所有成员。
成员变量是对象的属性(从设计角度),且它们保持私有来实现封装。这些变量只能使用公共成员函数来访问。
让我们使用上面的概念来设置和获取一个类中不同的类成员的值:
实例 using System; namespace BoxApplication { class Box { private double length; // 长度 private double breadth; // 宽度 private double height; // 高度 public void setLength( double len ) { length = len; } public void setBreadth( double bre ) { breadth = bre; } public void setHeight( double hei ) { height = hei; } public double getVolume() { return length * breadth * height; } } class Boxtester { static void Main(string[] args) { Box Box1 = new Box(); // 声明 Box1,类型为 Box Box Box2 = new Box(); // 声明 Box2,类型为 Box double volume; // 体积 // Box1 详述 Box1.setLength(6.0); Box1.setBreadth(7.0); Box1.setHeight(5.0); // Box2 详述 Box2.setLength(12.0); Box2.setBreadth(13.0); Box2.setHeight(10.0); // Box1 的体积 volume = Box1.getVolume(); Console.WriteLine("Box1 的体积: {0}" ,volume); // Box2 的体积 volume = Box2.getVolume(); Console.WriteLine("Box2 的体积: {0}", volume); Console.ReadKey(); } } }
当上面的代码被编译和执行时,它会产生下列结果:
Box1 的体积: 210
Box2 的体积: 1560
C# 中的构造函数
类的 构造函数 是类的一个特殊的成员函数,当创建类的新对象时执行。
构造函数的名称与类的名称完全相同,它没有任何返回类型。
下面的实例说明了构造函数的概念:
实例 using System; namespace LineApplication { class Line { private double length; // 线条的长度 public Line() { Console.WriteLine("对象已创建"); } public void setLength( double len ) { length = len; } public double getLength() { return length; } static void Main(string[] args) { Line line = new Line(); // 设置线条长度 line.setLength(6.0); Console.WriteLine("线条的长度: {0}", line.getLength()); Console.ReadKey(); } } }
当上面的代码被编译和执行时,它会产生下列结果:
对象已创建
线条的长度: 6
默认的构造函数没有任何参数。但是如果你需要一个带有参数的构造函数可以有参数,这种构造函数叫做参数化构造函数。这种技术可以帮助你在创建对象的同时给对象赋初始值,具体请看下面实例:
实例 using System; namespace LineApplication { class Line { private double length; // 线条的长度 public Line(double len) // 参数化构造函数 { Console.WriteLine("对象已创建,length = {0}", len); length = len; } public void setLength( double len ) { length = len; } public double getLength() { return length; } static void Main(string[] args) { Line line = new Line(10.0); Console.WriteLine("线条的长度: {0}", line.getLength()); // 设置线条长度 line.setLength(6.0); Console.WriteLine("线条的长度: {0}", line.getLength()); Console.ReadKey(); } } }
当上面的代码被编译和执行时,它会产生下列结果:
对象已创建,length = 10
线条的长度: 10
线条的长度: 6
C# 中的析构函数
类的 析构函数 是类的一个特殊的成员函数,当类的对象超出范围时执行。
析构函数的名称是在类的名称前加上一个波浪形(~)作为前缀,它不返回值,也不带任何参数。
析构函数用于在结束程序(比如关闭文件、释放内存等)之前释放资源。析构函数不能继承或重载。
下面的实例说明了析构函数的概念:
实例 using System; namespace LineApplication { class Line { private double length; // 线条的长度 public Line() // 构造函数 { Console.WriteLine("对象已创建"); } ~Line() //析构函数 { Console.WriteLine("对象已删除"); } public void setLength( double len ) { length = len; } public double getLength() { return length; } static void Main(string[] args) { Line line = new Line(); // 设置线条长度 line.setLength(6.0); Console.WriteLine("线条的长度: {0}", line.getLength()); } } }
当上面的代码被编译和执行时,它会产生下列结果:
对象已创建
线条的长度: 6
对象已删除
C# 类的静态成员
我们可以使用 static 关键字把类成员定义为静态的。当我们声明一个类成员为静态时,意味着无论有多少个类的对象被创建,只会有一个该静态成员的副本。
关键字 static 意味着类中只有一个该成员的实例。静态变量用于定义常量,因为它们的值可以通过直接调用类而不需要创建类的实例来获取。静态变量可在成员函数或类的定义外部进行初始化。你也可以在类的定义内部初始化静态变量。
下面的实例演示了静态变量的用法:
实例 using System; namespace StaticVarApplication { class StaticVar { public static int num; public void count() { num++; } public int getNum() { return num; } } class StaticTester { static void Main(string[] args) { StaticVar s1 = new StaticVar(); StaticVar s2 = new StaticVar(); s1.count(); s1.count(); s1.count(); s2.count(); s2.count(); s2.count(); Console.WriteLine("s1 的变量 num: {0}", s1.getNum()); Console.WriteLine("s2 的变量 num: {0}", s2.getNum()); Console.ReadKey(); } } }
当上面的代码被编译和执行时,它会产生下列结果:
s1 的变量 num: 6
s2 的变量 num: 6
也可以把一个成员函数声明为 static。这样的函数只能访问静态变量。静态函数在对象被创建之前就已经存在。下面的实例演示了静态函数的用法:
实例 using System; namespace StaticVarApplication { class StaticVar { public static int num; public void count() { num++; } public static int getNum() { return num; } } class StaticTester { static void Main(string[] args) { StaticVar s = new StaticVar(); s.count(); s.count(); s.count(); Console.WriteLine("变量 num: {0}", StaticVar.getNum()); Console.ReadKey(); } } }
当上面的代码被编译和执行时,它会产生下列结果:
变量 num: 3