C#编程流程控制与集合类型(二)

简介: C#编程流程控制与集合类型

列表


列表与数组密切相关,列表能将相同类型的多个值收集到单个变量中。但是,在添加、删除和更新元素时,列表要灵活得多,这使列表在大多数情况下成为首选。

1.基本语法

列表类型的变量需要具备以下条件:

  • List 关键字,元素类型定义在后面的一对尖括号中,此外还要有唯一的名称。
  • new 关键字,用于初始化内存中的列表以及 List 关键字后面的一对尖括号中的元素类型。
  • 以分号结尾的一对括号。

以蓝图的形式看起来语法如下:

List<elementType> name = new List<elementType>();

注意:列表的长度总是可以修改的。因此,不需要在创建时就指定列表最终存储的元素数量

与数组一样,可以在变量的声明中通过在花括号内添加元素值来初始化列表:

List<elementType> name = new List<elementType>() {valuel, value2 };

元素从索引0开始按照添加的顺序进行存储,并且可以使用下标运算符进行访问。

实践一派对成员

下面通过在虚构的角色扮演游戏中创建派对成员列表来进行热身练习

(1)创建一个名为 questPartyMembers 的字符串类型的列表,并使用三个角色名称进行初始化。

(2)添加一条调试日志,使用 Count 方法打印出列表中的派对成员数量

(3)保存脚本并在Unity 中单击 Play 按钮,

image.png

刚刚发生了什么

我们初始化了一个名为questPartyMembers 的列表,其中存储了三个字符串,然后使用Count方法打印了列表中的元素数量

image.png

2.常用方法

只要索引在列表范围内,就可以像数组那样使用下标运算符和索引访问并修改列表元素。但是,List 类提供了多个用来扩展列表功能的方法,从而添加、插入和删除元素.

继续使用questPartyMembers列表。下面将一个新的成员添加到这个列表中:

questPartyMembers.Add("I am 4");

Add 方法可以将新元素追加到列表的末尾,这将使 questPartyMembers 列表的长度变为4,并使元素的顺序变为如下形式:

"I am 1","I am 2","I am 3","I am 4"

image.png

要在列表中的特定位置添加元素,可以向 Insert 方法传递想要添加的索引和值:

questPartyMembers.Insert(1,"I am 5");

删除元素非常简单,只需要提供索引或字面值,List 类即可完成工作:

1. questPartyMembers.RemoveAt(0);
2. questPartyMembers.Remove("I am 1");

字典


与数组和列表相比,字典在每个元素中存储值对而不是单个值。字典中的元素又称为键值对:键充当对应的值的索引。与数组和列表不同,字典是无序的。但是,典可以在创建后以各种配置进行排序。

1.基本语法

声明字典和声明列表几乎一样,但是许多细节(比如键和值的类型)需要在尖括号中进行指定:

Dictionary<keyType, valueType> name = new Dictionary<keytypevalueType>();

要使用键值对初始化字典,请执行以下操作:

  • 在声明的最后使用一对花括号。
  • 将每个元素添加到各自的一对花括号中,用逗号分隔键和值
  • 用逗号分隔元素,最后一个元素的逗号是可选的。
Dictionary<keyType, valueType> name = new Dictionary<keyType,valueType>()
{
 {keyl,valuel},
 {key2,valve2}
};

选择键值时,每个键必须唯一,并且不能更改。如果需要更新键,请在变量声明中更改对应的值,或者删除后重新添加。

提示:

就像使用数组和列表一样,可以在一行中初始化字典,这在 Visual Studio中没有问题。但是,与前面的示例一样,在每一行中写出完整的键值对是一种良好习惯,这有利于提高代码的可读性。

实践一建立库存

下面创建字典来存储角色可能携带的物品


(I)声明一个名为itemInventory 的字典,键的类型为string,值的类型为int


(2)将创建的字典初始化为 new Dictionary


(3)添加调试日志以打印itemInventory.Count 属性,以便查看存储的物品的数量


(4)保存脚本并在Unity 单击 Play 按钮

void Start()
{
 Dictionary<string, int> itemInventory = new Dictionary<string, int>()
 {
   {"potion",5},
   {"Antidote",7},
   {"Aspirin,1}
  };
  Debug.LogFormat("Items:{0}",itemInventory.Count};
}

刚刚发生了什么

我们创建了一个名为itemInventory 的字典,并使用三个键值对进行初始化。我们指定键为字符串类型、对应的值为整型,然后打印 itemInventory 字典中元素的数量

image.png

2使用字典对

可以使用下标和类方法在字典中添加、删除和访问键值对。要检索元素的值,请使用带元素键的下标运算符。如以下代码所示,numberOfPotions将被赋值为5:

int mumberofPotions = itemInventory["Potion"];

元素值可以使用同样的方法进行更改。与"Potion"关联的值现在是 10:

itemInventory["Potion"] = 10;

元素可以通过两种方式添加到字典中:使用Add 方法或下标运算符。Add 方法接收键和值,并使用它们创建新的键值对元素,只要类型与字典声明中的一致即可:

itemInventory.Add("Throwing Knife",3);

如果使用下标运算符为字典中不存在的键赋值,编译器将自动把它们添加为新的键值对。

如果想添加新的元素”Bandages”,可以使用以下代码

itemInventory{“WBandage"} = 5;

这就引出如下关于引用键值对的关键问题:最好在尝试访问一个元素之前确定这个元素是否存在,以免错误地添加新的键值对。将ContainsKey 方法与i语句配对是种简单的解决方案,因为ContainsKey 方法会根据键是否存在返回一个布尔值。在以下代码中,我们在确保"Aspirin"键存在后才更改对应的值:

if(itemInventory.ContainsKey("Aspirin"))
{
 itemInventory{"Aspirin"} = 3;
}

最后,可以使用 Remove 方法从字典中删除键值对,只需要传入键作为参数即可:

迭代


我们已经通过下标运算符和集合类型中的方法访问了各个集合元素,但是当需要逐个元素地遍历整个集合时,该怎么办呢?在编程中,这被称为迭代(iteration)。C#提供了几种语句类型,让我们可以遍历集合元素。迭代语句就像方法一样,它们可以存储将要执行的代码块;但与方法不同的是,只要满足条件,它们就可以重复执行代码块。

for循环


for 循环最常见的应用场景是:在程序继续之前需要执行某个代码块一定的次数for 循环语句本身包含三个表达式,每个表达式在执行循环之前都要执行特定的任务因为for 循环能够追踪正在进行的迭代,所以十分适用于数组和列表。

for 循环语句的蓝图如下:

1. for (initializer; condition; iterator)
2. {
3.    code block;
4. }

下面稍作分析:

  • 整个结构从 for 关键字开始,后面跟着一对括号
  • 括号内是三个表达式一一初始化表达式、条件表达式和迭代表达式
  • 循环从初始化表达式开始,可创建局部变量来追踪循环执行的次数通常设置为0,因为集合类型是从0开始索引的。
  • 接下来检查条件表达式,如果为 true,就进行选代。
  • 迭代表达式用于初始化变量的增减,这意味着下一次循环计算条件表达式时初始化变量会有所不同。

内容看起来好像很多,所以下面我们看看之前创建的questPartyMembers 列表示例:

image.png

下面看看其中的 for 循环是如何工作的

  • 初始化表达式将名为i的局部变量设置为0。
  • 确保只有当i小于questPartyMembers 中元素的数量时,for 循环才会执行
  • for 循环每执行一次就使用++运算符将i加1。
  • 在 for 循环内部,我们使用i打印出索引和索引处的列表元素。请注意,i 与集合元素的索引将保持一致,因为它们都是从0 开始的.

image.png

实践一查找元素

当遍历questPartyMembers 时,我们可以看看是否能迭代到某个确定的元素,并为这种情况添加特殊的调试日志。

(1)在for 循环的调试志的下面添加if语句。

(2)在if语句中检查当前的questPartyMembers 元素是否与”Merli the Wise"匹配

(3)如果匹配,就添加一条调试日志.\

image.png

控制台输出应该看起来几乎相同,只不过现在有一条额外的调试日志,并且这条日志仅在遍历到"I am 1"时才打印一次。具体而言,当i等于1,进入第二次循环,因为满足 if 语句中的条件,所以会打印两条调试日志而不是一条

image.png

foreach循环


foreach 循环能够获取集合中的每个元素并将其存储到局部变量中,从而可以在语句中访问它们。局部变量的类型必须与集合元素的类型匹配才能正常工作。foreach循环可以与数组和列表一起使用,但是它们对于字典来说尤为有用,因为它们不是基于数字索引的。

以蓝图的形式看起来语法如下:

1. foreach(elementType localName in collectionVariable)
2. {
3.  code block;
4. }

下面继续使用questPartyMembers列表示例,对其中的每个派对成员进行点名:

image.png

下面稍作分析:


元素类型被声明为字符串,从而能够与questPartyMembers 列表中的值匹配

创建一个名为 partyMember 的局部变量,用于在每次循环中保存元素。

i关键字的后面是想要遍历的集合,在本例中是questPartyMember 列表。我们得到的控制台输出

image.png

这比 for 循环要简单得多,但是在处理字典时,我们需要指出如下重要的区别:

如何将键值对作为局部变量处理.

遍历键值对

为了在局部变量中捕获键值对,需要使用 KeyValuePair 类型,同时分配键和值的类型以匹配字典中相应的类型。KeyValuePair 由于能够作为自身的类型,因此可与其他任何元素类型一样充当局部变量。

image.png

我们已经指定了命名为kvp 的 KeyValuePair 局部变量,这个变量的作用类似于 for循环的初始化表达式中的 i,用于将键和值的类型设置为字符串和整数以匹配itemlnventory

while循环


while 循环与 if 语句的相似之处在于,只要单个表达式或条件为 true,它们就可以运行。值的比较结果和布尔变量可以用作 while 条件,你也可以使用逻辑非运算符修改条件。


while 循环的语法如下:当条件为 true 时,就会一直运行代码块


在 while 循环中,通常需要声明一个初始化变量,就像在 for 循环中一样,然后在代码块的末尾手动对这个初始变量进行增减。根据自身的情况,初始化表达式通常是循环条件的一部分。

实践一追踪玩家是否还活着

在游戏中,假设我们需要在玩家活着时执行代码,并在玩家死亡时输出一些提示信息。

(1)创建一个int类型的名为 playerLives 的初始化变量,赋值为3。

(2)声明一个 while 循环,条件是检查 playerLives 是否大于0(判断玩家是否还活着)

(3)在 while 循环中,输出一些信息,从而让我们知道玩家还活着,然后使用--运算符将 playerLives 减1。

(4)在while循环的后面添加调试日志,从而在玩家死亡时打印一些内容,

image.png

刚刚发生了什么

playerLives从3 开始,因而 while 循环执行了3次。循环期间会打印"Stillalive!"”并从 playerLives 中减去生命值。当第4 次运行 while 循环时,因为 playerLives为0所以循环条件不满足,于是代码块被跳过,打印 while 循环后面的调试日志

image.png

超越无限


在结束本章之前,我们需要理解关于迭代语句的一个极其重要的概念:无限循环顾名思义,无限循环指的就是循环无法停止,因而将在程序中一直运行。


在 for和 while 循环中,当迭代变量不增加或减少时,通常会发生无限循环。例如.在之前的 while 循环示例中,如果去掉 playerLives 代码行,Unity 就会崩溃,因光playerLives 始终为3,循环会永远执行下去。


另外,在 for 循环中,永远不会通过或计算为 false 的设置条件,也可能导致无限循环。在遍历键值对时,如果将 for 循环条件设置为 i>0 而不是iquestPartyMembers.Count,那么i永远不会小于0,for 循环会一直运行下去直到Unity崩溃。

总结


至此,我们应该反思自己已经完成了多少工作以及利用这些知识可以创建什么。我们已经知道如何使用简单的 felse 语句和复杂的switch 语句在代码中做出决策。我们可以使用数组、列表或带键值对的字典来创建存储各种值的集合变量,甚至可以为每种集合类型选择正确的循环语句,同时谨慎地避免无限循环。如果感到任务过重,没有关系一-逻辑和顺序思考是锻炼编程能力的有效方式。下面将通过研究类、结构体和面向对象编程(通常称为 OOP)来结束对 C#编程基础知识的讨论。我们将把到目前为止所学的一切都放到对这些主题的讨论之中,从而为第一次真正地深入了解和控制Unity引擎中的对象做好准备。


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
11天前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
|
11天前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
|
11天前
|
存储 安全 网络安全
C#编程的安全性与加密技术
【4月更文挑战第21天】C#在.NET框架支持下,以其面向对象和高级特性成为安全软件开发的利器。本文探讨C#在安全加密领域的应用,包括使用System.Security.Cryptography库实现加密算法,利用SSL/TLS保障网络传输安全,进行身份验证,并强调编写安全代码的重要性。实际案例涵盖在线支付、企业应用和文件加密,展示了C#在应对安全挑战的同时,不断拓展其在该领域的潜力和未来前景。
|
11天前
|
人工智能 C# 开发者
C#编程中的图形界面设计
【4月更文挑战第21天】本文探讨了C#在GUI设计中的应用,介绍了Windows Forms、WPF和UWP等常用框架,强调了简洁界面、响应式设计和数据绑定等最佳实践。通过实际案例,展示了C#在企业应用、游戏开发和移动应用中的GUI实现。随着技术发展,C#在GUI设计的未来将趋向于跨平台、更丰富的组件和AI集成,为开发者创造更多可能性。
|
2月前
|
C#
24. C# 编程:用户设定敌人初始血值的实现
24. C# 编程:用户设定敌人初始血值的实现
22 0
|
11天前
|
存储 算法 C#
C#编程与数据结构的结合
【4月更文挑战第21天】本文探讨了C#如何结合数据结构以构建高效软件,强调数据结构在C#中的重要性。C#作为面向对象的编程语言,提供内置数据结构如List、Array和Dictionary,同时也支持自定义数据结构。文章列举了C#实现数组、链表、栈、队列等基础数据结构的示例,并讨论了它们在排序、图算法和数据库访问等场景的应用。掌握C#数据结构有助于编写高性能、可维护的代码。
|
11天前
|
开发框架 Linux C#
C#编程的跨平台应用
【4月更文挑战第21天】C#与.NET Core的结合使得跨平台应用开发变得高效便捷,提供统一编程模型和高性能。丰富的类库、活跃的社区支持及Visual Studio Code、Xamarin等工具强化了其优势。广泛应用在企业系统、云服务和游戏开发中,虽面临挑战,但随着技术进步,C#在跨平台开发领域的前景广阔。
|
11天前
|
人工智能 C# 云计算
C#编程的未来发展趋向
【4月更文挑战第21天】C#编程未来将深化跨平台支持,强化云计算与容器技术集成,如.NET Core、Docker。在AI和ML领域,C#将提供更丰富框架,与AI芯片集成。语言和工具将持续创新,优化异步编程,如Task、async和await,提升多核性能。开源生态的壮大将吸引更多开发者,共创更多机遇。
|
11天前
|
程序员 C#
C#编程中的面向对象编程思想
【4月更文挑战第21天】本文探讨了C#中的面向对象编程,包括类、对象、封装、继承和多态。类是对象的抽象,定义属性和行为;对象是类的实例。封装隐藏内部细节,只暴露必要接口。继承允许类复用和扩展属性与行为,而多态使不同类的对象能通过相同接口调用方法。C#通过访问修饰符实现封装,使用虚方法和抽象方法实现多态。理解并应用这些概念,能提升代码的清晰度和可扩展性,助你成为更好的C#程序员。
|
11天前
|
开发框架 安全 .NET
C#编程高手的成长之路
【4月更文挑战第21天】本文揭示了成为C#编程高手的路径:牢固掌握基础知识和面向对象编程,深入了解C#特性如泛型和委托,精通ASP.NET等框架工具,养成良好编程习惯,持续学习实践并参与开源项目,勇于挑战创新。通过这些步骤,不断提升编程技能,迈向C#编程的巅峰。