没有合适的资源?快使用搜索试试~ 我知道了~
如何使用函数(如何使用函数如何使用函数c#)
需积分: 9 29 浏览量
2009-04-08
07:29:36
上传
评论
收藏 402KB PDF 举报
温馨提示
如何使用函数如何使用函数如何使用函数如何使用函数
资源详情
资源评论
资源推荐

第 7 章如何使用函数
在面向过程开发中,程序是由函数组成的,可以说,在那个年代,函数就是应用程序的基石。函数与
函数之间的关系也成了软件开发架构中极其重要的一个方面。而现如今,在面向对象开发中,函数的地位
已被类所取代,但它仍起着重要的作用——在类的两大组成部分(数据与操作)中,它占据了半壁江山。
从另一个层面上说,即使是面向对象开发,在具体细节层面上,面向过程仍是不可或缺的编程模式。本章
将从面向过程的角度,详细讨论函数的使用。
7.1 为什么要使用函数
很多开发人员都知道如何定义函数并调用它,但不见得每个人都能用好它。也许很多时候,只是为了
使用函数而使用函数。其实,引入任何一个新的概念或者技术之前,最关键的问题并不是如何使用它,而
是为什么要使用它。只有深刻理解了使用它的初衷,才有可能将其用得恰当。本节将讨论引入函数机制的
几个主要理由。
7.1.1 函数与方法
首先,我要先解释一组容易被混淆的概念:函数与方法。它们实际上所指的东西几乎相同,但在不同
的情景下我们会使用不同的术语。函数是与语句对应的概念,它是从编程语言本身的机制及语法结构角度
来看的;方法则是与对象、属性、事件等平行的概念,它是从面向对象的功能角度来看的。在 C# 中,类
/对象的方法是由函数来实现的,但并非所有的函数都是方法。事实上,属性最终也是由函数机制来实现
的,虽然在语法上看起来有些区别,但其实质并没有改变。例如属性:
private int age = 0;
public int Age
{
get { return age; }
set { age = value; }
}
其实就可以视为下面两个函数的一种语法上的整合:
private int age = 0;
public int GetAge()
{
return age;
}

public void SetAge(int value)
{
age = value;
}
除此之外,有些函数创建的本意,并非是在面向对象中向类型提供新的方法,而是出于与面向过程编
程中使用函数相同的理由。例如:
private bool ValidateMonth(int month)
{
if (1 <= month && month <= 12)
{
return true;
}
else
{
return false;
}
}
我们并不打算给当前类添加一个 ValidateMonth 方法,这只是供该类中的其他代码调用的一个函数,这
类函数虽然从语法上来说确实为当前类提供了一个方法,但从语义上来说,它只是一个普通的函数。通常
来说,访问性为 private 的函数都不是真正的方法,因为它并不会对外提供可执行操作,而只是在类的内
部被调用。
7.1.2 代码复用
最早人们使用函数的目的,就是为了减少代码重复——这也是各类编程书籍中提及最多的理由。在程
序中往往会遇到一些需要多次使用的代码,它们有时是原封不动地重复出现,有时只有非常微小的变化。
例如下面这段代码:
graphics.DrawRectangle(new Pen(Color.Black, 2), 8, 8, 150, 23);
StringFormat format1 = new StringFormat();
format1.Alignment = StringAlignment.Center;
format1.LineAlignment = StringAlignment.Center; graphics.DrawString(
"Box A",
new Font("Verdana", 9),
new SolidBrush(Color.Black),
new RectangleF(8, 8, 150, 23),
format1
);
graphics.DrawRectangle(new Pen(Color.Black, 2), 8, 35, 150, 23);
StringFormat format2 = new StringFormat();
format2.Alignment = StringAlignment.Center;

format2.LineAlignment = StringAlignment.Center; graphics.DrawString(
"Box B",
new Font("Verdana", 9),
new SolidBrush(Color.Black),
new RectangleF(8, 35, 150, 23),
format2
);
我们画了两个带有居中文本的方框,如果需要三个或者更多的话,复制代码不但显得笨拙,而且不便
于代码修改。循环可以在一定程度上解决这类问题,但我们不得不特别创建一些数组或集合来向循环提供
数据。此时最好的办法就是使用一个函数:
代码示例 0-1:使用函数复用代码
private void DrawBoxWithText(
int x,
int y,
int width,
int height,
Color foregroundColor,
int borderThickness,
string text,
Font font
)
{
graphics.DrawRectangle(new Pen(foregroundColor, borderThickness),
x, y, width, height);
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
graphics.DrawString(
text,
font,
new SolidBrush(foregroundColor),
new RectangleF(x, y, width, height),
format
);
}
当需要绘制时,调用这个函数即可:
(续代码示例 0-1:使用函数复用代码)
DrawBoxWithText(8, 8, 150, 23, Color.Black, 2, "Box A", "Verdana", 9);
DrawBoxWithText(8, 35, 150, 23, Color.Black, 2, "Box B", "Verdana", 9);
如果我们需要修改绘图方式时,只需一次性修改函数,就算需要添加更多的参数,编译系统也会帮助

我们找到所有调用这个函数的位置,不至于出现遗漏。
7.1.3 隐藏细节
你也许会不相信,但时至今日,函数最主要的目的(除了向类提供方法之外)并非代码复用,而是隐
藏细节。这可能与面向对象中的抽象有一点相似,不过你很快就能体会到它们的差别。
先看下面的这段程序:
public void ProcessDataFile(string sourceFile, string destinationFile)
{
List<int> numbers = new List<int>();
FileStream fs = new FileStream(sourceFile, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
try
{
while (r.PeekChar() != -1)
{
numbers.Add(r.ReadInt16());
}
}
finally
{
r.Close();
}
fs.Close();
int sum = 0;
foreach (int number in numbers)
{
sum += number;
}
double average = (double)sum / numbers.Count;
fs = new FileStream(destinationFile, FileMode.OpenOrCreate);
BinaryWriter w = new BinaryWriter(fs);
w.Write(average);
w.Close();
fs.Close();

}
这段程序看起来很乱,它其实主要做了三件事:先从源文件中读取一组数据,然后计算平均值,最后
将计算结果写入目标文件中。既然我们在思考的时候首先是将其分解为三件事,而不是每一个细节步骤,
那么程序也应当尽可能地反映出这种逻辑,于是我们可以将这三件事分别写成三个函数:
代码示例 0-2:使用函数进行抽象
public void ProcessDataFile(string sourceFile, string destinationFile)
{
List<int> numbers = ReadDataFromFile(sourceFile);
double average = GetAverage(numbers);
WriteDataToFile(destinationFile);
}
private List<int> ReadDataFromFile(string sourceFile) {
List<int> numbers = new List<int>();
FileStream fs = new FileStream(sourceFile, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
try
{
while (r.PeekChar() != -1)
{
numbers.Add(r.ReadInt16());
}
}
finally
{
r.Close();
}
fs.Close();
return numbers;
}
private double GetAverage(List<int> numbers) {
int sum = 0;
foreach (int number in numbers)
{
sum += number;
}
double average = (double)sum / numbers.Count;
剩余20页未读,继续阅读











haitianpanjun
- 粉丝: 0
- 资源: 10
上传资源 快速赚钱
我的内容管理 收起
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助


会员权益专享
安全验证
文档复制为VIP权益,开通VIP直接复制

评论0