Методы (Руководство по программированию на C#)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. В C# все инструкции выполняются в контексте метода.In C#, every executed instruction is performed in the context of a method. Метод Main является точкой входа для каждого приложения C#, и он вызывается общеязыковой средой выполнения (CLR) при запуске программы.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.

Примечание

В этом разделе рассматриваются названные методы.This topic discusses named methods. Сведения об анонимных функциях см. в разделе Анонимные функции.For information about anonymous functions, see Anonymous Functions.

Сигнатуры методовMethod Signatures

Методы объявляются в классе или в структуре путем указания уровня доступа, такого как public или private, необязательных модификаторов, таких как abstract или sealed, возвращаемого значения, имени метода и всех параметров этого метода.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.

Примечание

Тип возврата метода не является частью сигнатуры метода в целях перегрузки метода.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. Таким образом, методы класса Motorcycle могут вызываться, как показано в следующем примере: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. Вы можете передавать тип значения по ссылке с помощью ключевого слова ref.You can pass a value-type by reference by using the ref keyword. Дополнительные сведения см. в разделе Передача параметров типа значения.For more information, see Passing Value-Type Parameters. Список встроенных типов значений см. в разделе Таблица типов значений.For a list of built-in value types, see Value Types Table.

При передаче в метод объекта ссылочного типа передается ссылка на этот объект.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.

Ссылочный тип создается с помощью ключевого слова class , как показано в следующем примере.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. В следующем примере объект типа SampleRefType передается в метод ModifyObject.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. В данном случае в методе ModifyObject изменено поле value параметра obj, а также изменено поле value аргумента, rtв методе TestRefType .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. В качестве выходных данных метод TestRefType отображает 33.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 and Reference Types.

Возвращаемые значенияReturn Values

Методы могут возвращать значение вызывающему объекту.Methods can return a value to the caller. Если тип возврата, указываемый перед именем метода, не void, этот метод может возвращать значение с помощью ключевого слова return .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. Инструкция с ключевым словом return , за которым следует значение, соответствующее типу возврата, будет возвращать это значение объекту, вызвавшему метод.A statement with the return keyword followed by a value that matches the return type will return that value to the method caller.

Значение может возвращаться вызывающему объекту по значению или, начиная с C# версии 7.0, по ссылке.The value can be returned to the caller by value or, starting with C# 7.0, by reference. Значения возвращаются вызывающему объекту по ссылке, если ключевое слово ref используется в сигнатуре метода и указывается после каждого ключевого слова return.Values are returned to the caller by reference if the ref keyword is used in the method signature and it follows each return keyword. Например, следующая сигнатура метода и оператор return указывают, что метод возвращает имена переменных estDistance вызывающему объекту по ссылке.For example, the following method signature and return statement indicate that the method returns a variable names estDistance by reference to the caller.

public ref double GetEstimatedDistance()
{
   return ref estDistance;
}

Ключевое слове return также останавливает выполнение метода.The return keyword also stops the execution of the method. Если тип возврата — void, инструкцию return без значения по-прежнему можно использовать для завершения выполнения метода.If the return type is void, a return statement without a value is still useful to stop the execution of the method. Без ключевого слова return этот метод будет останавливать выполнение при достижении конца блока кода.Without the return keyword, the method will stop executing when it reaches the end of the code block. Методы с типом возврата, отличным от void, должны использовать ключевое слово return для возврата значения.Methods with a non-void return type are required to use the return keyword to return a value. Например, в следующих двух методах ключевое слово return используется для возврата целочисленных значений.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);

Использование локальной переменной, в данном случае 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.

Чтобы использовать значение, возвращаемое по ссылке из метода, необходимо объявить локальную ссылочную переменную, если планируется изменение значения.To use a value returned by reference from a method, you must declare a ref local variable if you intend to modify its value. Например, если метод Planet.GetEstimatedDistance возвращает значение Double по ссылке, можно определить его как локальную ссылочную переменную с использованием кода следующего вида:For example, if the Planet.GetEstimatedDistance method returns a Double value by reference, you can define it as a ref local variable with code like the following:

ref int distance = plant 

Возвращать многомерный массив из метода M, который изменяет содержимое массива, необязательно, если вызывающая функция передает массив в M.Returning a multi-dimensional array from a method, M, that modifies the array's contents is not necessary if the calling function passed the array into M. В целях оптимизации можно возвращать полученный массив из M или функциональный поток значений, однако это необязательно. Это связано с тем, что C# передает все ссылочные типы по значению, а значение ссылки на массив представляет собой указатель на массив.You may return the resulting array from M for good style or functional flow of values, but it is not necessary because C# passes all reference types by value, and the value of an array reference is the pointer to the array. В методе M любые изменения содержимого массива отслеживаются любым кодом, имеющим ссылку на массив, как показано в приведенном ниже примере.In the method M, any changes to the array's contents are observable by any code that has a reference to the array, as shown in the following example.

static void Main(string[] args)  
        {  
            int[,] matrix = new int[2, 2];  
            FillMatrix(matrix);  
            // matrix is now full of -1  
        }  

        public static void FillMatrix(int[,] matrix)  
        {  
            for (int i = 0; i < matrix.GetLength(0); i++)  
            {  
                for (int j = 0; j < matrix.GetLength(1); j++)  
                {  
                    matrix[i, j] = -1;  
                }  
            }  
        }  

Для получения дополнительной информации см. return.For more information, see return.

Асинхронные методыAsync Methods

С помощью функции async можно вызывать асинхронные методы, не прибегая к использованию явных обратных вызовов или ручному разделению кода между несколькими методами или лямбда-выражениями.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.

Если пометить метод с помощью модификатора async , можно использовать в этом методе инструкцию await .If you mark a method with the async modifier, you can use the await operator in the method. Когда управление достигает выражения await в асинхронном методе, управление возвращается вызывающему объекту и выполнение метода приостанавливается до завершения выполнения ожидающей задачи.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.

Примечание

Асинхронный метод возвращается в вызывающий объект, когда он встречает первый ожидаемый объект, выполнение которого еще не завершено, или когда выполнение асинхронного метода доходит до конца — в зависимости от того, что происходит раньше.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.

Асинхронный метод может иметь тип возврата Task<TResult>, Taskили void.An async method can have a return type of Task<TResult>, Task, or void. Тип возврата void в основном используется для определения обработчиков событий, где требуется тип возврата void.The void return type is used primarily to define event handlers, where a void return type is required. Асинхронный метод, который возвращает тип void, не может быть ожидающим. Вызывающий объект метода, возвращающего значение типа void, не может перехватывать исключения, которые выдает этот метод.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.

В следующем примере DelayAsync является асинхронным методом с типом возврата Task<TResult>.In the following example, DelayAsync is an async method that has a return type of Task<TResult>. DelayAsync имеет инструкцию return , которая возвращает целое число.DelayAsync has a return statement that returns an integer. Поэтому объявление метода DelayAsync должно иметь тип возврата Task<int>.Therefore the method declaration of DelayAsync must have a return type of Task<int>. Поскольку тип возврата — Task<int>, вычисление выражения await в DoSomethingAsync создает целое число, как показывает следующая инструкция: int result = await delayTask.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.

В следующем примере метод startButton_Click служит примером асинхронного метода с типом возврата void.The startButton_Click method is an example of an async method that has a return type of void. Поскольку DoSomethingAsync является асинхронным методом, задача для вызова DoSomethingAsync должна быть ожидаемой, как показывает следующая инструкция: await DoSomethingAsync();.Because DoSomethingAsync is an async method, the task for the call to DoSomethingAsync must be awaited, as the following statement shows: await DoSomethingAsync();. Метод startButton_Click должен быть определен с модификатором async , так как этот метод имеет выражение await .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

Асинхронный метод не может объявить все параметры ref или out, но может вызвать методы, которые имеют такие параметры.An async method can't declare any ref or out parameters, but it can call methods that have such parameters.

Дополнительные сведения об асинхронных методах см. в разделах Асинхронное программирование с использованием ключевых слов async и await, Поток управления в асинхронных программах и Асинхронные типы возврата.For more information about async methods, see Asynchronous Programming with async and await, Control Flow in Async Programs, and Async Return Types.

Определения текста выраженийExpression Body Definitions

Часто используются определения методов, которые просто немедленно возвращаются с результатом выражения или которые имеют единственную инструкцию в тексте метода.It is common to have method definitions that simply return immediately with the result of an expression, or that have a single statement as the body of the method. Для определения таких методов существует сокращенный синтаксис с использованием =>:There is a syntax shortcut for defining such methods using =>:

public Point Move(int dx, int dy) => new Point(x + dx, y + dy);   
public void Print() => Console.WriteLine(First + " " + Last);  
// Works with operators, properties, and indexers too.  
public static Complex operator +(Complex a, Complex b) => a.Add(b);  
public string Name => First + " " + Last;   
public Customer this[long id] => store.LookupCustomer(id);  

Если метод возвращает void или является асинхронным методом, то текст метода должен быть выражением инструкции (так же, как при использовании лямбда-выражений).If the method returns void or is an async method, then the body of the method must be a statement expression (same as with lambdas). Свойства и индексаторы должны быть только для чтения, и вы не должны использовать ключевое слово get метода доступа.For properties and indexers, they must be read only, and you don't use the get accessor keyword.

ИтераторыIterators

Итератор выполняет настраиваемую итерацию по коллекции, например по списку или массиву.An iterator performs a custom iteration over a collection, such as a list or an array. Итератор использует инструкцию yield return для возврата всех элементов по одному.An iterator uses the yield return statement to return each element one at a time. Когда достигается инструкция yield return , текущее расположение в коде запоминается.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.

Итератор вызывается из клиентского кода с помощью инструкции foreach .You call an iterator from client code by using a foreach statement.

Тип возврата итератора может быть IEnumerable, IEnumerable<T>, IEnumeratorили IEnumerator<T>.The return type of an iterator can be IEnumerable, IEnumerable<T>, IEnumerator, or IEnumerator<T>.

Дополнительные сведения см. в разделе Итераторы.For more information, see Iterators.

Спецификация языка C#C# Language Specification

Дополнительные сведения см. в спецификации языка C#.For more information, see the C# Language Specification. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.The language specification is the definitive source for C# syntax and usage.

См. такжеSee Also

Руководство по программированию на C#C# Programming Guide
Классы и структурыClasses and Structs
Модификаторы доступаAccess Modifiers
Статические классы и члены статических классовStatic Classes and Static Class Members
НаследованиеInheritance
Абстрактные и запечатанные классы и члены классовAbstract and Sealed Classes and Class Members
paramsparams
returnreturn
outout
refref
Передача параметровPassing Parameters