Partilhar via


Methods (C# Programming Guide)

A method is a code block that contains a series of statements. A program causes the statements to be executed by calling the method and specifying any required method arguments. In C#, every executed instruction is performed in the context of a method. The Main method is the entry point for every C# application and it is called by the common language runtime (CLR) when the program is started.

Note

This topic discusses named methods. For information about anonymous functions, see Anonymous Functions (C# Programming Guide).

Method Signatures

Methods are declared in a class or struct by specifying the access level such as public or private, optional modifiers such as abstract or sealed, the return value, the name of the method, and any method parameters. These parts together are the signature of the method.

Note

A return type of a method is not part of the signature of the method for the purposes of method overloading. However, it is part of the signature of the method when determining the compatibility between a delegate and the method that it points to.

Method parameters are enclosed in parentheses and are separated by commas. Empty parentheses indicate that the method requires no parameters. This class contains three methods:

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(); 
}

Method Access

Calling a method on an object is like accessing a field. After the object name, add a period, the name of the method, and parentheses. Arguments are listed within the parentheses, and are separated by commas. The methods of the Motorcycle class can therefore be called as in the following example:

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);            
    }
}

Method Parameters vs. Arguments

The method definition specifies the names and types of any parameters that are required. When calling code calls the method, it provides concrete values called arguments for each parameter. The arguments must be compatible with the parameter type but the argument name (if any) used in the calling code does not have to be the same as the parameter named defined in the method. For example:

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;
}

Passing by Reference vs. Passing by Value

By default, when a value type is passed to a method, a copy is passed instead of the object itself. Therefore, changes to the argument have no effect on the original copy in the calling method. You can pass a value-type by reference by using the ref keyword. For more information, see Passing Value-Type Parameters (C# Programming Guide). For a list of built-in value types, see Value Types Table (C# Reference).

When an object of a reference type is passed to a method, a reference to the object is passed. That is, the method receives not the object itself but an argument that indicates the location of the object. If you change a member of the object by using this reference, the change is reflected in the argument in the calling method, even if you pass the object by value.

You create a reference type by using the class keyword, as the following example shows.

public class SampleRefType
{
    public int value;
}

Now, if you pass an object that is based on this type to a method, a reference to the object is passed. The following example passes an object of type SampleRefType to method 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;
}

The example does essentially the same thing as the previous example in that it passes an argument by value to a method. But, because a reference type is used, the result is different. The modification that is made in ModifyObject to the value field of the parameter, obj, also changes the value field of the argument, rt, in the TestRefType method. The TestRefType method displays 33 as the output.

For more information about how to pass reference types by reference and by value, see Passing Reference-Type Parameters (C# Programming Guide) and Reference Types (C# Reference).

Return Values

Methods can return a value to the caller. If the return type, the type listed before the method name, is not void, the method can return the value by using the return keyword. A statement with the return keyword followed by a value that matches the return type will return that value to the method caller. The return keyword also stops the execution of the method. If the return type is void, a return statement without a value is still useful to stop the execution of the method. Without the return keyword, the method will stop executing when it reaches the end of the code block. Methods with a non-void return type are required to use the return keyword to return a value. For example, these two methods use the return keyword to return integers:

class SimpleMath
{
    public int AddTwoNumbers(int number1, int number2)
    {
        return number1 + number2;
    }

    public int SquareANumber(int number)
    {
        return number * number;
    }
}

To use a value returned from a method, the calling method can use the method call itself anywhere a value of the same type would be sufficient. You can also assign the return value to a variable. For example, the following two code examples accomplish the same goal:

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);

Using a local variable, in this case, result, to store a value is optional. It may help the readability of the code, or it may be necessary if you need to store the original value of the argument for the entire scope of the method.

For more information, see return (C# Reference).

Async Methods

By using the async feature, you can invoke asynchronous methods without using explicit callbacks or manually splitting your code across multiple methods or lambda expressions. The async feature was introduced Visual Studio 2012.

If you mark a method with the async modifier, you can use the await operator in the method. When control reaches an await expression in the async method, control returns to the caller, and progress in the method is suspended until the awaited task completes. When the task is complete, execution can resume in the method.

Note

An async method returns to the caller when either it encounters the first awaited object that’s not yet complete or it gets to the end of the async method, whichever occurs first.

An async method can have a return type of Task<TResult>, Task, or void. The void return type is used primarily to define event handlers, where a void return type is required. An async method that returns void can't be awaited, and the caller of a void-returning method can't catch exceptions that the method throws.

In the following example, DelayAsync is an async method that has a return type of Task<TResult>. DelayAsync has a return statement that returns an integer. Therefore the method declaration of DelayAsync must have a return type of Task<int>. Because the return type is Task<int>, the evaluation of the await expression in DoSomethingAsync produces an integer as the following statement demonstrates: int result = await delayTask.

The startButton_Click method is an example of an async method that has a return type of void. Because DoSomethingAsync is an async method, the task for the call to DoSomethingAsync must be awaited, as the following statement shows: await DoSomethingAsync();. The startButton_Click method must be defined with the async modifier because the method has an await expression.

// 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

An async method can't declare any ref or out parameters, but it can call methods that have such parameters.

For more information about async methods, see Asynchronous Programming with Async and Await (C# and Visual Basic), Control Flow in Async Programs (C# and Visual Basic), and Async Return Types (C# and Visual Basic).

Iterators

An iterator performs a custom iteration over a collection, such as a list or an array. An iterator uses the yield return statement to return each element one at a time. When a yield return statement is reached, the current location in code is remembered. Execution is restarted from that location when the iterator is called the next time.

You call an iterator from client code by using a foreach statement.

The return type of an iterator can be IEnumerable, IEnumerable<T>, IEnumerator, or IEnumerator<T>.

For more information, see Iterators (C# and Visual Basic).

C# Language Specification

For more information, see the C# Language Specification. The language specification is the definitive source for C# syntax and usage.

See Also

Reference

Classes and Structs (C# Programming Guide)

Access Modifiers (C# Programming Guide)

Static Classes and Static Class Members (C# Programming Guide)

Inheritance (C# Programming Guide)

Abstract and Sealed Classes and Class Members (C# Programming Guide)

params (C# Reference)

return (C# Reference)

out (C# Reference)

ref (C# Reference)

Passing Parameters (C# Programming Guide)

Concepts

C# Programming Guide