辛巴学院-Unity-剑英陪你零基础学c#系列(四)函数和封装

2015年10月15日 11:35 0 点赞 0 评论 更新于 2025-11-21 19:11

国庆长假结束了,此刻我的心情就像下面歌词描述的一样:

你总是起不早,起不早
独自一个人沉睡到天亮
你无怨无悔的梦着那副本
我知道你根本就不想上班
你总是起不早,起不早
放假总是短暂,上班太难

请个病假,再睡上一天

言归正传,今天我们来聊聊C#的函数和封装。关于这个话题,相关资料数不胜数,无论是否有编程经验,大家或多或少都有所了解,我也很难给出新奇的见解,不过有一点需要先记住:这不是数学,这不是数学,这不是数学。

我最早接触的编程语言是Basic,那时函数还未深入人心,且我接触的是DOS时代的Basic,而非Visual Basic。当时有一些系统函数可以调用,但在编写小程序时,鲜少会去定义函数,甚至可能都不被允许定义,反正我在学习时对此一无所知。

或许有人会问,讲Basic干什么?这不是关于C#的文章吗?其实,我只是想说明,曾经存在不那么依赖函数和封装的编程语言,函数并非编程的必备要素。但C#以及C系语言,都是以函数和封装为基础构建的。那么,一个不用函数和封装的代码该怎么写呢?在过去的Basic中,代码有行号,可以使用goto语句跳转到指定行继续执行。我们可以依靠goto将代码划分为几块,让程序在不同代码块之间跳转。实际上,这就是一种没有语法保障的封装,本质上等同于函数。在C系语言中,同样可以使用goto,因为代码编译成机器语言后,本身就是通过类似goto的指令来实现跳转的。

将一块功能组织在一起,就叫做封装。专门将一块功能标记为一段子程序的语法,就是函数。

每一行代码都是宝贵的,这就像衣服,数量较少时(两三件),可以随意放置;但当数量增加到几十件时,不进行分类整理就会带来麻烦;当数量达到几百件时,可能需要分房间、分衣架来存放。这种对代码进行分类整理的需求就是封装的需求,它会随着系统复杂度的提升而自然出现。

如果你暂时无法体会到这种需求,那么可以先不考虑研究函数和封装,先用一个函数写完整个程序。如果最终你还是无法感受到封装的必要性,那你也能成为一名独特的程序员。

C#的函数语法如下:【修饰符】 类型 函数名(【参数1】,【参数2】,…){…}。这部分内容大家应该都比较熟悉,说与不说差别不大。

如何设计函数

关键在于,当你看到一个500行的函数时,是否会产生一种强烈的冲动,想要将其重新整理成多个函数?这种冲动是学习函数设计,也就是学习封装的关键。

你可能会发现,很多优秀的程序员虽然能写出高质量的代码,但却难以解释自己的设计方法和原则。这类程序员属于“本能型”,他们在掌握基本语法后,凭借对代码整理的直觉,逐步走向优秀。我认为“本能型”是最轻松的一种类型,热爱和悟性是他们最大的助力。

然而,并非所有人都能如此,有些人需要一些帮助才能找到学习的切入点。接下来,我们就来探讨一下函数的封装方法。

从命名开始

所有优秀的函数设计都始于命名,然后编写调用代码,至于函数的具体实现,可以稍后再考虑。如果你对此表示怀疑,没关系,我们先来谈谈命名的要点。

命名法有多种,比如著名的匈牙利命名法。命名法的使命是让名字清晰、准确、易于识别。以下是命名的一些规则:

  1. 使用英文:建议使用英文字母进行命名,避免使用中文或其他生僻字符。因为26个英文字母可以直接通过键盘输入,具有天然的优势。虽然不抵制使用拼音,但使用拼音会显得不够专业。同时,使用英文时要确保查清楚其语境和用法,避免随意使用。
  2. 遵循通用分隔规则:无论采用哪种命名法,通常由单词和分隔符两部分组成。常见的分隔符有下划线和驼峰法,不建议自创特别的分隔方法。使用简写时,要使用约定俗成的形式,不能随意规定简写规则,例如“inte”可能让人难以理解,应使用“Integer”或“int”;“cha”应使用“character”或“char”。
  3. 符合语法规则:函数名字应采用动宾短语,变量名字和类型名应采用定语修饰从句。例如,Void 打()不是一个好的命名,因为缺少宾语,无法明确“打”的对象;而Void 打豆豆()就清晰很多。Void 转圈()问题不大,因为可以容易推断出是自己转圈。这里使用中文只是为了说明问题,实际编程中应使用英文。对于变量命名,如Int 金币Int 豆豆的金币,要从语文的角度确保表达清晰。

先写调用,再写实现

新手程序员通常认为应该先写函数的实现,而有经验的程序员则统一认为应该先写调用。我们来思考几个问题:

  • 在程序运行之前,程序员是否知道程序的运行顺序?答案是肯定的。
  • 对于一个不知道其细节实现的函数,程序员是否能使用?答案是可以。
  • 观察程序结构时,看到结构末端时是否需要查看函数实现?答案是不需要。

程序设计就是在程序运行之前规划好其运行方式,而规划程序运行方式就需要设计程序的结构,即确定函数之间的调用关系。不知道函数的实现细节并不影响程序设计。因此,永远先写调用,再写实现,是程序设计的基本原则。

函数设计原则

为了帮助大家更好地设计函数,以下是一些函数设计的原则:

  1. 函数长度:函数不宜过长,一般来说,100行以上的函数就需要重新审视。虽然不同人可能对合适的长度有不同的看法,但总体原则是函数要易于理解。
  2. 聚焦功能:函数命名应明确其功能,函数的参数、返回值和实现都应围绕该功能进行。如果函数的行为与命名不符,应考虑将其拆分为其他函数。一个好的函数应该在不查看实现的情况下就能理解其作用。
  3. 一致性:函数应保持一致性,即相同的输入应产生相同的输出。虽然有些函数(如随机数函数)看起来输入相同但输出不同,但实际上它们有隐形输入(如随机种子)。在设计函数时,要慎重考虑隐形状态,确保函数从外部易于观察。例如,addrandhp(10)函数的行为是加5到15点血,这种设计包含了隐藏的随机状态,不易理解;而Addrandhp(5,15)的设计方式能让外部更容易理解函数的行为。
  4. 错误处理:函数应尽早检查输入的合法性,在执行过程中出错时,应给予正常的异常反馈。虽然关于异常处理有不同的方法论,但微软的类库倾向于尽早抛出异常,我们可以遵循这种风格。

不知不觉中,这个零基础系列的内容可能变得有些复杂了,或许我更适合写一些有深度的文章,需要自我反省一下。

再会,哈库拉玛塔塔

作者:李剑英 原文:http://www.taidous.com/bbs/thread-33999-1-1.html

作者信息

洞悉

洞悉

共发布了 3994 篇文章