方法(C# 编程指南)
“方法”是包含一系列语句的代码块。程序通过“调用”方法并指定所需的任何方法参数来执行语句。在 C# 中,每个执行指令都是在方法的上下文中执行的。Main 方法是每个 C# 应用程序的入口点,在启动程序时由公共语言运行时 (CLR) 调用。
说明 |
---|
本主题讨论命名方法。有关匿名函数的信息,请参见 匿名函数(C# 编程指南)。 |
方法签名
通过指定方法的访问级别(例如 public 或 private)、可选修饰符(例如 abstract 或 sealed)、返回值、名称和任何方法参数,可以在类或结构中声明方法。这些部分统称为方法的“签名”。
说明 |
---|
为进行方法重载,方法的返回类型不是方法签名的一部分。但是,在确定委托和委托所指向方法之间的兼容性时,返回类型是方法签名的一部分。 |
方法参数括在括号中,并用逗号隔开。空括号表示方法不需要参数。下面的类包含三个方法:
abstract class Motorcycle
{
// Anyone can call this.
public void StartEngine() {/* Method statements here */ }
// Only derived classes can call this.
protected void AddGas(int gallons) { /* Method statements here */ }
// Derived classes can override the base class implementation.
public virtual int Drive(int miles, int speed) { /* Method statements here */ return 1; }
// Derived classes must implement this.
public abstract double GetTopSpeed();
}
方法访问
在对象上调用方法类似于访问字段。在对象名称之后,依次添加句点、方法名称和括号。参数在括号内列出,并用逗号隔开。因此,可以按以下示例中的方式调用 Motorcycle 类的方法:
class TestMotorcycle : Motorcycle
{
public override double GetTopSpeed()
{
return 108.4;
}
static void Main()
{
TestMotorcycle moto = new TestMotorcycle();
moto.StartEngine();
moto.AddGas(15);
moto.Drive(5, 20);
double speed = moto.GetTopSpeed();
Console.WriteLine("My top speed is {0}", speed);
}
}
方法参数与. 参数
方法定义指定所需任何“形参”的名称和类型。调用代码在调用方法时,将为每个形参提供称为“实参”的具体值。实参必须与形参类型兼容,但调用代码中使用的实参名称(如果有)不必与方法中定义的形参名称相同。例如:
public void Caller()
{
int numA = 4;
// Call with an int variable.
int productA = Square(numA);
int numB = 32;
// Call with another int variable.
int productB = Square(numB);
// Call with an integer literal.
int productC = Square(12);
// Call with an expression that evaulates to int.
productC = Square(productA * 3);
}
int Square(int i)
{
// Store input argument in a local variable.
int input = i;
return input * input;
}
通过使用. 引用传递的值。
默认情况下,将值类型传递给方法时,传递的是副本而不是对象本身。因此,对参数所做的更改对于调用方法中的原始副本没有影响。可以使用 ref 关键字通过引用传递值类型。有关更多信息,请参见传递值类型参数(C# 编程指南)。有关内置值类型的列表,请参见值类型表(C# 参考)。
当引用类型的对象传递给方法时,对对象的引用传递。即方法接收不是对象,还指示对象的位置的参数。如果更改对象的成员通过使用该引用,更改反映在被调用的方法的参数,因此,即使通过对象的值。
如下面的示例所示,通过使用 class 关键字,则创建一个引用类型。
public class SampleRefType
{
public int value;
}
现在,因此,如果您通过根据方法的此类型的对象,对对象的引用传递。下面的示例通过类型 SampleRefType 对象传递给方法 ModifyObject。
public static void TestRefType()
{
SampleRefType rt = new SampleRefType();
rt.value = 44;
ModifyObject(rt);
Console.WriteLine(rt.value);
}
static void ModifyObject(SampleRefType obj)
{
obj.value = 33;
}
该示例实质上执行操作与前例同样因为它通过值传递实参传递给方法。但,使用引用类型,则结果是不同的。在对该参数进行 value 字段的 ModifyObject 做的修改,obj,也会更改参数,rt的 value 字段,在 TestRefType 方法。TestRefType 方法显示 33 作为输出。
有关如何通过引用传递的更多信息类型通过值引用,请参见 传递引用类型参数(C# 编程指南) 和 引用类型(C# 参考)。
返回值
方法可以向调用方返回值。如果返回类型(方法名称前列出的类型)不是 void,则方法可以使用 return 关键字来返回值。如果语句中 return 关键字的后面是与返回类型匹配的值,则该语句将该值返回给方法调用方。return 关键字还会停止方法的执行。如果返回类型为 void,则可使用没有值的 return 语句来停止方法的执行。如果没有 return 关键字,方法执行到代码块末尾时即会停止。具有非 void 返回类型的方法才能使用 return 关键字返回值。例如,下面的两个方法使用 return 关键字来返回整数:
class SimpleMath
{
public int AddTwoNumbers(int number1, int number2)
{
return number1 + number2;
}
public int SquareANumber(int number)
{
return number * number;
}
}
若要使用从方法返回的值,调用方法可以在本来使用同一类型的值就已足够的任何位置使用方法调用本身。还可以将返回值赋给变量:例如,下面的两个代码示例可实现相同的目的:
int result = obj.AddTwoNumbers(1, 2);
result = obj.SquareANumber(result);
// The result is 9.
Console.WriteLine(result);
result = obj.SquareANumber(obj.AddTwoNumbers(1, 2));
// The result is 9.
Console.WriteLine(result);
使用局部变量,在这种情况下,result,存储值是可选的。这有助于提高代码的可读性,并且如果要为方法的整个范围存储参数的原始值,可能必须这样做。
有关更多信息,请参见return(C# 参考)。
异步方案
使用异步功能,可以异步调用方法,而不使用显式回调或手动拆分您在多个方法或 lambda 表达式中的代码。异步功能是表示的 Visual Studio 2012。
如果标记与 异步 修饰符的方法,在方法可以使用 等待 运算符。当控件移到在异步方法中的一个等待表达式,控件回调用方,因此,在方法的进度挂起,直到等待任务完成。当任务完成后,执行在方法可以恢复。
说明 |
---|
异步方法回调用方,当数组中遇到不是完成后或者具有异步方法的末尾的第一个等待的对象,后者首先进行。 |
异步方法可以具有 Task<TResult>、Task或无效的返回类型。返回类型为 void 主要用于定义事件处理程序,返回类型为 void 需要。返回 void 的异步方法不能等待和无效返回的方法的调用方无法捕获方法引发的异常。
在下面的示例中,DelayAsync 是具有 Task<TResult>的一个返回类型的异步方法。DelayAsync 具有返回整数的一个 return 语句。因此 DelayAsync 的方法声明必须具有 Task<int>的返回类型。由于返回类型为 Task<int>,await 表达式的计算 DoSomethingAsync 的生成一个整数,如下面的语句示:int result = await delayTask。
startButton_Click 方法是具有无效的一个返回类型异步方法的示例。由于 DoSomethingAsync 是异步方法,必须等待调用的任务,DoSomethingAsync,如以下语句示:await DoSomethingAsync();。因为方法具有一个 await 表达式,必须定义 startButton_Click 方法与 async 修饰符。
// using System.Diagnostics;
// using System.Threading.Tasks;
// This Click event is marked with the async modifier.
private async void startButton_Click(object sender, RoutedEventArgs e)
{
await DoSomethingAsync();
}
private async Task DoSomethingAsync()
{
Task<int> delayTask = DelayAsync();
int result = await delayTask;
// The previous two statements may be combined into
// the following statement.
//int result = await DelayAsync();
Debug.WriteLine("Result: " + result);
}
private async Task<int> DelayAsync()
{
await Task.Delay(100);
return 5;
}
// Output:
// Result: 5
异步方法不能声明任何 ref 或 out 或参数,但是,它能调用具有这些参数的方法。
有关异步方法的更多信息,请参见 使用 Async 和 Await 的异步编程(C# 和 Visual Basic)、异步程序中的控制流(C# 和 Visual Basic)和 异步返回类型(C# 和 Visual Basic)。
迭代器
迭代器对集合的自定义迭代,如列表或数组。迭代器使用 将返回 语句返回每个元素一个节点。当 将返回 语句时,代码的当前位置确保。迭代器,当下次时,调用执行从该位置进行重新启动。
使用 foreach 语句,则调用从客户端代码中的迭代器。
迭代器的返回类型可以是 IEnumerable、IEnumerable<T>、IEnumerator或 IEnumerator<T>。
有关更多信息,请参见迭代器(C# 和 Visual Basic)。
C# 语言规范
有关更多信息,请参见 C# 语言规范。该语言规范是 C# 语法和用法的权威资料。