——本系列是基于人民邮电出版社《C#2008 C#图解教程》、清华大学出版社《C#入门经典(第五版)》两本书的自学C#笔记,如果您发现了本文的纰漏,还望不吝指正。
在 C#笔记10 类:基础 中,我们已经知道,方法是类中重要的一个函数成员
除了类中,方法也可以声明在结构体,接口中
*复习:方法是具有名称的可执行代码块,当方法被调用时,它执行自己所含的代码,然后返回到调用它的代码。有些方法返回一个值到它们被调用的位置。
在类的相关笔记中,我们已经知道了如何声明一个简单的方法,
还是上次的例子:
class SimpleClass
{
void PrintNum() //没有返回值,参数列表为空
{
ConsoleWriteLine("1"); //{}内为方法体
}
}
我们把方法分成有两个主要部分:方法头和方法体
本地变量和字段一样,用来保存数据,但是本地变量的影响范围仅限于当前方法块
本地常量和本地变量一样,影响范围仅限于当前方法块
关于常量,参考 C#笔记11 类:类成员补充01中的成员常量
——上图出自 人民邮电出版社《C#2008 C#图解教程》第5章
使用方法名调用方法
例:以下代码展示了在同一类中创造出类的实例,调用其他方法,实际上即使是不同类中的调用方法是相同的
class NumberManipulator
{
public int FindMax(int num1, int num2)
{
/* 局部变量声明 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
static void Main(string[] args)
{
/* 局部变量定义 */
int a = 100;
int b = 200;
int ret;
NumberManipulator n = new NumberManipulator();
//调用 FindMax 方法
ret = n.FindMax(a, b);
Console.WriteLine("最大值是: {0}", ret );
Console.ReadLine();
}
}
//代码来自 菜鸟教程 https://www.runoob.com/csharp/csharp-methods.html
控制台输出结果:
最大值是: 200
*静态方法的调用方法,同静类的外部访问静态成员,使用点(.)运算符,类名.成员名
方法可以向调用代码返回一个值。返回的值被插入到调用代码中发起调用的表达式所在的位置
必须在方法名前声明返回类型
例:下边代码中,GetHour()方法前的int,代表了这个方法,会返回int类型
int GetHour()
{
DateTime dt = DateTime:Now; // 获取当前日期和时间
int hour = dt.Hour; // 获取小时数
return hour; //返回一个int
}
例:返回的类型也可以是用户定义的类型
MyClass method3()
{
MyClass mc = new MyClass();
return mc; // 返回一个Myclass对象
}
关键字return:
必须在方法名前声明返回类型为void
void方法:
例:
void SomeMethod()
{
if(SomeCondition)
return;
}
就是方法头中圆括号里的内容,没有内容的话就是无参方法
声明在方法的参数列表中,而不是方法体中的本地变量
上边的例子中,方法 FindMax中,圆括号中的"num1, num2",就是两个int类型的形参
public int FindMax(int num1, int num2) { }
方法被调用时,用于初始化形参的表达式或变量,实参放在方法调用的参数列表中
还是上边的例子中,调用 FindMax 方法时,ret = n.FindMax(a, b),圆括号中的"a,b",就是两个int类型的实参
int a = 100;
int b = 200;
int ret;
NumberManipulator n = new NumberManipulator();
//调用 FindMax 方法
ret = n.FindMax(a, b);
数据通过复制实参的值到形参的方式传递到函数
实参和形参使用的是两个不同内存中的值(因为系统在栈中为形参单独分配了内存)。在这种情况下,当形参的值发生改变时,不会影响实参的值,从而保证了实参数据的安全。
例:下面的代码中,把myNumber作为一个参数,调用ShowDouble()并不影响myNumber的值,即使赋予val的参数被加倍,myNumber的值也不变。
static void ShowDouble(int val)
{
val *= 2;
Console.WriteLine("val doubled = {0}", val);
}
//参数val在这个函数中被加倍,如果按以下方式调用它:
int myNumber = 5;
Console.WriteLine("myNumber = {0}", myNumber);
ShowDouble(myNumber);
Console.WriteLine("myNumber = {0}", myNumber);
控制台输出结果:
myNumber = 5
val doubled = 10
myNumber = 5
即方法处理的变量与方法调用中使用的变量相同,而不仅仅是值相同的变量(因为系统不会为形参单独分配内存,而是直接引用实参的内存位置)。因此,对这个变量进行的任何改变都会影响用作参数的变量值。
例:还是上边的代码,在方法的参数列表中,加入ref关键字,使用引用参数。这次,myNumber的值就被ShowDouble()修改了。
static void ShowDouble(ref int val)
{
val *= 2;
Console.WriteLine("val doubled = {0}", val);
}
//添加ref关键字后的调用:
int myNumber = 5;
Console.WriteLine("myNumber = {0}", myNumber);
ShowDouble(ref myNumber); //传参时也必须有ref
Console.WriteLine("myNumber = {0}", myNumber);
控制台输出结果:
myNumber = 5
val doubled = 10
myNumber = 10
通过参数列表可以额外输出一个信息(return 语句可用于只从函数中返回一个值。可以使用输出参数来从函数中返回两个值)
在方法使用out参数时,out参数必须看作是还未赋值
在被读取之前,方法返回之前,必须被赋值
例:下面的代码中,方法MaxValue返回一个int值(return maxVal),在参数列表中加入一个out int maxIndex,让方法额外输出一个int值(maxIndex)
static int MaxValue(int[] intArray, out int maxIndex)
{
int maxVal = intArray[0];
maxIndex = 0;
for (int i = 1; i < intArray.Length; i++)
{
if (intArray[i] > maxVal)
{
maxVal = intArray[i];
maxIndex = i; //函数返回之前,maxIndex被赋值
}
}
return maxVal;
}
//可以采用以下方式使用该函数:
int[] myArray = { 1, 8, 3, 6, 2, 5, 9, 3, 0, 2 };
int maxIndex;
//使用out参数时,out参数还未赋值
Console.WriteLine("The maximum value in myArray is {0}", MaxValue(myArray, out maxIndex));
Console.WriteLine("The first occurrence of this value is at element {0}",maxIndex + 1);
控制台输出结果:
The maximum value in myArray is 9
The first occurrence of this value is at element 7
上边所有的参数类型,都必须严格遵守一个实参对应一个形参,而参数数组则允许零个或者多个实参对应到这个特殊的形参。
1).在函数定义时,在数据类型前加上
2).params修饰的参数必须是数组类型
3).必须放在方法参数列表的最后一位,并且只能有一个参数数组
例:如下方法头中,形参intVals可以代表零个或多个int实参
void ListInts( params int[] intVals) { }
ListInts( 10, 20 , 30 );
int[] intArray = { 1, 2, 3 };
ListInts( intArray );
例:下面的代码延续上边例子中定义的方法
class MyClass
{
public void ListInts(params int[] intVals)
{
if ((intVals != null) && (intVals.Length != 0))
{
for (int i = 0; i < intVals.Length; i++)
{
intVals[i] = intVals[i] * 10;
Console.WriteLine(intVals[i]);
}
}
}
}
class Program
{
static void Main()
{
int a = 5, b = 6, c = 7;
Console.WriteLine("{0},{1},{2}", a, b, c);
MyClass mc = new MyClass();
mc.ListInts(a, b, c);
Console.WriteLine("————分割线————");
int[] intArray = { 1, 2, 3 };
Console.WriteLine("{0},{1},{2}", intArray[0], intArray[1], intArray[2]);
mc.ListInts(intArray);
}
}
控制台输出结果:
5,6,7
50
60
70
————分割线————
1,2,3
10
20
30