C# 基本概念7

本文深入探讨了结构和数组的基础概念及应用,包括结构的特点、结构与类的区别、数组的维度和初始化方法等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

结构

结构和类非常相似。和类相比,结构更加适合用于表示轻量
级对象(如复数、坐标、矩阵、颜色等)。通过结构,
只要使用少量数据成员,就能够表示这些轻量级对象,
从而简化了应用程序。
  结构概述;
  结构成员;
  结构和类的区别
  创建Point 结构;
  创建Complex 结构。


结构概述

结构(struct )与类非常相似,它们都表示可以包含数据成
员(常量和字段)和函数成员(方法、属性、事件、索
引器、运算符、实例构造函数和静态构造函数)的数据
结构。但是,结构是一种值类型,结构类型的变量直接
包含了该结构的数据。类类型是一种引用类型,类类型
1 .结构声明
2 .结构修饰符


结构成员

结构和类一样,它也包含多种成员,如常量、字段、方法等,具体说明
如下。
  常量
  字段
  方法
  属性
  事件
  索引器
  运算符
  实例构造函数
  静态构造函数
  类型
上述成员除了类型之外,可以分类两大类:数据成员和函数成员。其中
,数据成员包括常量和字段;函数成员包括方法、属性、事件、索引
器、运算符、实例构造函数和静态构造函数。


结构和类的区别

结构和类虽然比较相似,但是还存在以下8 个方面的区别。
结构是值类型,并隐式地从类System.ValueType 继承,而类是引用类型,并从类
object 继承。
结构总是分配在堆栈上,而类常常分配在堆上。如果对结构类型的变量进行赋值
,那么将创建所赋的值的一个副本。
结构类型字段的默认值是字段本身的类型的默认值,而类类型字段的默认值为null
。因此,结构是存在默认值的。
结构不能声明无参数的实例构造函数。
结构不能声明析构函数。
在结构中,初始化实例字段是错误的。
对于结构而言,不像类那样存在继承。一个结构不能从另一个结构或类继承,而
且不能作为一个类的基。但是,结构从基类Object 继承。结构可实现接口,其
方式同类完全一样。
实例化结构时,可以不使用new 运算符,而且结构对象的字段具有默认初始值。而
实例化类时,必须使用new 运算符,并需要设置各个字段的初始值。


继承

结构不支持继承。因此,在声明结构成员时,不能使用
protected 或protected internal 修饰符。结构类型永远不会
是抽象的,并且始终是隐式密封的。因此,结构不能作
为其他结构或类的基结构,而且在声明结构时,不能使
用abstract 或sealed 修饰符。


this 保留字

this 是一个保留字,它只能在实例构造函数、实例方法或实
例访问器的块中使用,且表示当前实例。在类中,this 表
示当前实例,它的值不能被修改。在结构中,this 相当于
一个变量。如果在结构的实例构造函数中,this 相当于一
个结构类型的out 参数;如果在结构的实例函数成员中,
this 相当于一个结构类型的ref 参数。


构造函数

在结构中,不能声明无参数的实例构造函数。其实,每一个
结构都隐式地具有一个无参数实例构造函数,该构造函
数将初始化该结构所有字段的值。如果字段的类型为值
类型,则将该字段的值设置为其类型的默认值。如果字
段的类型为引用类型,则将该字段的值设置为null 。
另外,结构还可以声明带有参数的实例构造函数。

数组

数组可以将多个类型相同的元素组合为一个整体,从而通过
数组统一访问或操作这些元素。数组是C# 语言最常用的
数据结构之一。它是相同数据类型的对象的集合。该集
合的长度(即数组的长度)可以为0 或大于0 的整数。本
章将讲解使用数组进行编程的方法。
  数组概述;
  数组分类;
  静态数组;
  动态数组;
  抽签程序。


数组概述

数组是一个有序的数据集合。数组中的每一个元素的数据类
型都相同。元素的数据类型被称为元素类型,它可以为
任何类型,甚至可以为数组。数组可以用一个统一的数
组名和下标来唯一确定组中的元素。例如,一个班有50
名学生,可以用s 1 、s 2 、s 3 、… 、s 50 表示50 个学生的成绩
。s 为数组名,下标表示学生的序号。s 10 (整数10 为下标
)表示第10 个学生的成绩。


数组的维度数

大家都知道,直线由点构成,平面由直线构成、空间由平面
构成。如果要描述直线上的一个点,则只需要一个值。
如果要描述平面上的一个点,则需要两个值。如果要描
述空间中的一个点,则需要3 个值。在直线、平面和空间
中,称描述一个点所需要值的数量为“维度数”。
数组也一样,它也存在维度数的概念。当在要描述数组中的
一个元素时,如果只需要一个值(数组的下标),那么
该数组的维度数为1 ;如果需要两个值,那么该数组的维
度数为2 ;依次类推。如上述提及的s 数组的维度数就是1
。根据数组的维度数不同,可以把数组分为以下3 种类型
  一维数组,维度数为1 的数组。
  二维数组,维度数为2 的数组。
  多维数组,维度数大于2 的数组。


声明数组

在C# 程序设计中,如果需要某一个数组,则必须首先声明
该数组。声明一维数组的语法如下所示。
type[] arrayName;
其中,type 表示数组元素的类型,如int 、double 、string 、
object 等;arrayName 表示数组的名称。


实例化数组

实例化数组就是为数组分配相应的内存。注意,声明一个数
组,并不为该数组分配相应的内存。


初始化数组

初始化数组就是初始化数组中每一个元素的值,即为数组中
的每一个元素进行赋值。数组被实例化之后,每个元素
都为其元素类型的默认值。一般情况下,只有初始化数
组之后,该数组才具有实际运算的意义。初始化数组存
有多种方法,主要包括以下4 种。
1 .直接赋值
2 .使用“new” 操作符,并指定了数组的长度
3 .使用“new” 操作符,省略数组的长度
4 .直接设置数组的每一个元素的值


遍历数组

遍历数组是指依次访问数组中的每一个元素,并执行预先设
计的操作。访问数组的元素最常用方法之一就是使用下
标(或索引)。根据是否使用下标可以遍历数组方式分
为两种。第一种,使用下标遍历,如for 、while 、
do…while 等语句。第二种,不使用下标遍历,如foreach
语句。
1 .使用下标遍历数组
2 .不使用下标遍历数组


数组分类

根据数组的维度数和元素的类型不同,可以把数组分为4 种
类型:一维数组(维度数为1 的数组)、二维数组(维度
数为2 的数组)、多维数组(维度数大于2 的数组)和交
错数组(元素的类型为数组的数组)。本小节将介绍声
明、实例化和初始化各种不同类型数组的方法。


一维数组

一维数组是指维度数为1 的数组,它是最简单的数组,也是
最常用的数组。声明一维数组的语法如下所示。
type[] arrayName;
其中,type 表示数组元素的类型,如int 、double 、string 、
object 等;arrayName 表示数组的名称。


二维数组

二维数组是指维度数为2 的数组。声明二维数组的语法如下
所示。
type[,] arrayName;
其中,type 表示数组元素的类型,如int 、double 、string 、
object 等;中括号([] )中间存在一个逗号(, )表示该数
组为一个二维数组;arrayName 表示数组的名称。


多维数组

多维数组是指维度数大于2 的数组,如三维数组、四维数组
等。声明三维数组的语法如下所示。
type[, ,] arrayName;
其中,type 表示数组元素的类型,如int 、double 、string 、
object 等;中括号([] )中间存在两个逗号(, )表示该数
组为一个三维数组;arrayName 表示数组的名称。


交错数组

交错数组又称为“数组的数组”,它的元素也为一个数组。
声明二维交错数组的语法如下所示。
type[][] arrayName;
其中,type 表示数组元素的类型,如int 、double 、string 、
object 等;type 关键字之后包含两个中括号([] )表示该
数组为一个二维交错数组;arrayName 表示数组的名称。


静态数组 System.Array

.NET 框架提供了两种数组:静态数组和动态数组。一旦为
数组分配内存之后,如果该数组的大小是不能修改的,
则称该数组为静态数组;反之,则称之为动态数组。静
态数组静态数组由System.Array 类实现,动态数组由
System.ArrayList 类实现。本小节将介绍静态数组的基本
属性和方法,以及它们的使用方法。


属性

System.Array 类包含7 个属性,如获取数组长度的Length 属性、获
取数组秩的Rank 等,如表10.1 所示。
属性  描述
Length  数组的长度,即数组所有维度中元素的总数。
该值为32位整数。
LongLength  数组的长度,即数组所有维度中元素的总数。
该值为64位整数。
Rank  数组的秩,即数组的维度数。
IsFixedSize  表示数组的大小是否固定。
IsReadOnly  表示数组是否为只读。
IsSynchronized  表示是否同步访问数组。
SyncRoot  获取同步访问数组的对象。


方法

System.Array 类包含多个方法,如获取数组长度的GetLength() 方法
、获取指定元素值的GetValue() 方法,获取指定元素索引的
IndexOf() 方法等,如表10.2 所示。
属性  描述
GetValue()  获取指定元素的值。
SetValue()  设置指定元素的值。
Clear()  清空数组中的所有元素。
GetLength()  获取指定维的元素数量。该值为32位整数。
GetLongLength()  获取指定维的元素数量。该值为64位整数。
IndexOf()  获取匹配的第一个元素的索引。
LastIndexOf()  获取匹配的最后一个元素的索引。
FindIndex()  搜索指定元素,并获取第一个匹配元素的索引。
FindLastIndex()  搜索指定元素,并获取最后一个匹配元素的索引。
Copy()  将一个数组中的一部分元素复制到另一个数组。
CopyTo()  将一维数组的所有元素复制到另外一个一维数组。
Clone()  复制数组。
ConstrainedCopy()  指定开始位置,并复制一系列元素到另外一个数组中。
Sort()  对一维数组中的元素进行排序。
Reverse()  反转一维数组中元素的顺序。
BinarySearch()  使用二进制搜索算法在一维的排序数组中搜索指定元素。
GetLowerBound()  获取数组中指定维度的下限。
GetUpperBound()  获取数组中指定维度的上限。


获取数组长度

数组长度是指数组元素的总数,即数组每一维度元素数量之
乘积。获取数组长度的方法存在多种,可以通过
System.Array 类的属性获取,也可以通过Array 类的方法
获取。
1 .通过属性获取数组的长度
2 .通过方法获取数组的长度


获取元素的值

获取数组中指定元素的值最简单方法就是通过“[]” 运算符



设置元素的值

和获取指定元素的值一样,也存在两种方法设置元素的值。
第一种方法就是直接通过数组名和“[]” 运算符来设置元
素的值。


获取元素的索引

System.Array 类为一维数组提供了获取元素的索引的两个静
态方法:IndexOf() 和LastIndexOf() 方法。IndexOf() 方法
获取匹配的、第一个元素的索引。LastIndexOf() 方法获
取匹配的、最后一个元素的索引。


排序数组

System.Array 类为一维数组提供了一个名称为“Sort()” 的方
法,该方法可以对一维数组中的元素进行排序。能够使
用Sort() 方法排序的数组中的元素必须实现IComparable
接口,即数组中的元素是能够进行比较的,否则不能对
该数组中的元素进行排序。


反转数组

System.Array 类为一维数组提供了一个名称为“Reverse()”
的方法,该方法可以反转一维数组中的全部元素或部分
连续的元素。


动态数组 System.ArrayList

动态数组又称为可变数组,且数组的长度可以动态修改。动
态数组由System.ArrayList 类实现,它在保存元素时,仅
仅保存元素的引用,而不是元素的具体值。因此,动态
数组元素的数据类型可以是任何类型,而且各个元素的
数据类型也可以不相同。


属性

System.ArrayList 类包含了7 个属性,如获取数组元素数量的Count
属性、指示数组是否为只读的ReadOnly 属性等,如表10.3 所示。
属性  描述
Capacity  数组的容量。
Count  数组元素的数量。
Item  指定索引处的元素。
IsFixedSize  表示数组的大小是否固定。
IsReadOnly  表示数组是否为只读。
IsSynchronized  表示是否同步访问数组。
SyncRoot  获取同步访问数组的对象。


方法

System.ArrayList 类包含了多个方法,如添加新元素到数组
末尾中的Add() 方法、从数组中删除指定元素的Remove()
方法等。


添加元素

向动态数组添加一个新的元素可以使用Add() 方法或者
Insert() 方法。Add() 方法可以将新的元素添加到数组的末
尾处,Insert() 方法可以将新的元素添加到数组的指定位
置。如果希望把新的元素插入到数组(元素数量大于0 )
的开始处,则只能使用Insert() 方法。


移除元素

如果要从动态数组中移除元素,则可以使用Remove() 、
RemoveAt() 或RemoveRange() 方法。Remove() 方法从数
组中移除指定的元素,RemoveAt() 方法从数组中移除指
定位置处的元素,RemoveRange() 方法从数组中移除指定
范围内的元素。
接口
接口和类一样,也是属于引用类型。接口可以用来描述属于
类或结构的一组相关功能,即定义一种协议。类或结构
可以实现接口,同时必须遵循它们所实现接口定义的协
议。本章将讲解C# 语言中的接口,主要介绍以下知识点

  接口概述;
  接口成员;
  实现接口;
  抽象类和接口。


接口概述

接口(interface )定义一种协议,实现该接口的类或结构必
须遵循该协议。一个接口可以继承于一个或多个其他接
口,一个类或结构也可以实现一个或多个接口。接口可
以包含4 种成员:方法、属性、事件和索引器。接口本身
不提供它所定义的成员的实现,它仅仅指定实现该接口
的类或结构必须提供的成员。


接口声明

声明接口需要使用interface 关键字,语法如下。
interface-modifiers interface identifier interface-base
interface-body ;
interface-modifiers 表示接口修饰符(可选),identifier 表示
接口的名称,interface-base 表示接口的基接口(可选)
,interface-body 表示接口体,; (分号)是可选的。4


接口修饰符

接口修饰符一般位于接口声明中的interface 关键字之前,共
包括5 个修饰符:new 、public 、protected 、internal 和
private 。其中,public 、protected 、internal 和private 修
饰符控制接口的可访问性。它们的意义具体说明如下。
 public 修饰符,表示该接口是公开的,访问不受限制。
 protected 修饰符,表示该接口只能是本身或其派生的接
口访问。
 internal 修饰符,表示该接口只能是在当前应用程序中访
问。
 private 修饰符,表示该接口只能是本身访问。


接口继承

接口可以继承于一个或多个其他接口,也可以不继承。被继
承的接口称为该接口的显式基接口。当一个接口具有一
个或多个显式基接口时,在声明该接口时,接口标识符
后就要紧跟一个冒号和一个由, (逗号)分隔的基接口标
识符列表。


接口成员

接口的成员必须是方法、属性、事件或索引器,而不能包括
常量、字段、运算符、实例构造函数、析构函数或类型
,也不能包含任何种类的静态成员。一个接口可以不包
括任何成员,也可以包括一个或多个成员。接口成员默
认隐式地具有public 访问属性,而且在声明接口成员时不
能包含任何修饰符(如abstract 、public 、protected 、
internal 、private 、virtual 、override 和static ),否则会
发生编译时错误。
注意:一个接口的成员包括两部分:由接口本身声明的成员
和其从基接口继承的成员。


属性

在接口中声明属性时,只能声明该属性具有哪个访问器(如
get 或set 访问器),而不能实现该访问器。接口属性的访
问器只用于表明该属性是只读的、只写的还是读写的,
访问器体必须始终是一个; (分号)。


索引器

接口索引器和接口属性比较相似。在接口中声明索引器时,
只能声明该索引器具有哪个访问器(如get 或set 访问器)
,而不能实现该访问器。接口索引器的访问器只用于表
明该索引器是只读的、只写的还是读写的,访问器体必
须始终是一个; (分号)。


方法

在接口中声明方法时,只能声明该方法的签名,而且该方法
的方法体只能为; (分号),而不能包括该方法的实现代
码。


事件

在接口中声明事件时,只能声明该事件的签名,而且事件的
名称之后必须接一个; (分号)。


实现接口

类和结构都可以实现接口。如果某一个类或接口实现了一个
或多个接口,那么在声明该类或结构时,将实现的接口
的标识符包含在该类或结构的基类列表中。


实现属性

实现接口属性即添加该接口属性的实现代码,接口属性的名
称和实现该接口属性的名称相同。


实现索引器

实现接口索引器即添加该接口索引器的实现代码。


实现方法

实现接口方法即添加该接口方法的实现代码,接口方法的名
称和实现该接口方法的签名相同。


实现事件

实现接口事件即添加该接口事件的实现代码,接口事件的名
称和实现该接口事件的签名相同。


抽象类和接口

抽象类使用abstract 修饰符,它用于表示所修饰的类是不完
整的,并且它只能用作基类。抽象类与非抽象类在以下3
个方面的区别。
  抽象类不能直接实例化。如果抽象类使用new 运算符,则
发生编译时错误。
  允许(但不要求)抽象类包含抽象成员。
  抽象类不能被密封。
当从抽象类派生非抽象类时,这些非抽象类必须实现所继承
的所有抽象成员,即重写这些抽象成员。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值