Métodos (Guía de programación de C#)Methods (C# Programming Guide)

Un método es un bloque de código que contiene una serie de instrucciones.A method is a code block that contains a series of statements. Un programa hace que se ejecuten las instrucciones al llamar al método y especificando los argumentos de método necesarios.A program causes the statements to be executed by calling the method and specifying any required method arguments. En C#, todas las instrucciones ejecutadas se realizan en el contexto de un método.In C#, every executed instruction is performed in the context of a method. El método Main es el punto de entrada para cada aplicación de C# y se llama mediante Common Language Runtime (CLR) cuando se inicia el programa.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.

Nota

En este tema se analizan los métodos denominados.This topic discusses named methods. Para obtener información sobre las funciones anónimas, vea Funciones anónimas (Guía de programación de C#).For information about anonymous functions, see Anonymous Functions.

Firmas de métodoMethod Signatures

Los métodos se declaran en una clase o struct especificando el nivel de acceso, como public o private, modificadores opcionales como abstract o sealed, el valor de retorno, el nombre del método y cualquier parámetro de método.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. Todas estas partes forman la firma del método.These parts together are the signature of the method.

Nota

Un tipo de valor devuelto de un método no forma parte de la firma del método con el objetivo de sobrecargar el método.A return type of a method is not part of the signature of the method for the purposes of method overloading. Sin embargo, forma parte de la firma del método al determinar la compatibilidad entre un delegado y el método que señala.However, it is part of the signature of the method when determining the compatibility between a delegate and the method that it points to.

Los parámetros de método se encierran entre paréntesis y se separan por comas.Method parameters are enclosed in parentheses and are separated by commas. Los paréntesis vacíos indican que el método no requiere parámetros.Empty parentheses indicate that the method requires no parameters. Esta clase contiene cuatro métodos:This class contains four 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(); 
}

Acceso a métodosMethod Access

Llamar a un método en un objeto es como acceder a un campo.Calling a method on an object is like accessing a field. Después del nombre del objeto, agregue un punto, el nombre del método y paréntesis.After the object name, add a period, the name of the method, and parentheses. Los argumentos se enumeran entre paréntesis y están separados por comas.Arguments are listed within the parentheses, and are separated by commas. Los métodos de la clase Motorcycle se pueden llamar como en el ejemplo siguiente: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);            
    }
}

Parámetros de métodos frente a ArgumentosMethod Parameters vs. Arguments

La definición del método especifica los nombres y tipos de todos los parámetros necesarios.The method definition specifies the names and types of any parameters that are required. Si el código de llamada llama al métodos, proporciona valores concretos denominados argumentos para cada parámetro.When calling code calls the method, it provides concrete values called arguments for each parameter. Los argumentos deben ser compatibles con el tipo de parámetro, pero el nombre del argumento (si existe) utilizado en el código de llamada no tiene que ser el mismo que el parámetro con nombre definido en el método.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. Por ejemplo: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;
 }

Pasar por referencia frente a Pasar por valorPassing by Reference vs. Passing by Value

De forma predeterminada, cuando un tipo de valor se pasa a un método, se pasa una copia en lugar del propio objeto.By default, when a value type is passed to a method, a copy is passed instead of the object itself. Por lo tanto, los cambios realizados en el argumento no tienen ningún efecto en la copia original del método de llamada.Therefore, changes to the argument have no effect on the original copy in the calling method. Puede pasar un tipo de valor por referencia mediante la palabra clave ref.You can pass a value-type by reference by using the ref keyword. Para obtener más información, vea Pasar parámetros de tipo de valor (Guía de programación de C#).For more information, see Passing Value-Type Parameters. Para obtener una lista de tipos de valor integrados, vea Tabla de tipos de valor (Referencia de C#).For a list of built-in value types, see Value Types Table.

Cuando se pasa un objeto de un tipo de referencia a un método, se pasa una referencia al objeto.When an object of a reference type is passed to a method, a reference to the object is passed. Es decir, el método no recibe el objeto concreto, recibe un argumento que indica la ubicación del objeto.That is, the method receives not the object itself but an argument that indicates the location of the object. Si cambia un miembro del objeto mediante esta referencia, el cambio se refleja en el argumento del método de llamada, incluso si pasa el objeto por valor.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.

Crea un tipo de referencia mediante la palabra clave class , como se muestra en el siguiente ejemplo.You create a reference type by using the class keyword, as the following example shows.

public class SampleRefType
{
    public int value;
}

Ahora, si se pasa un objeto basado en este tipo a un método, también se pasa una referencia al objeto.Now, if you pass an object that is based on this type to a method, a reference to the object is passed. En el ejemplo siguiente se pasa un objeto de tipo SampleRefType al método 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;
}

Fundamentalmente, el ejemplo hace lo mismo que el ejemplo anterior en el que se pasa un argumento por valor a un método.The example does essentially the same thing as the previous example in that it passes an argument by value to a method. Pero, debido a que se utiliza un tipo de referencia, el resultado es diferente.But, because a reference type is used, the result is different. La modificación que se lleva a cabo en ModifyObject al campo value del parámetro, obj, también cambia el campo value del argumento, rt, en el método 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. El método TestRefType muestra 33 como salida.The TestRefType method displays 33 as the output.

Para obtener más información sobre cómo pasar tipos de referencia por valor y por referencia, vea Pasar parámetros Reference-Type (Guía de programación de C#) y Tipos de referencia (Referencia de C#).For more information about how to pass reference types by reference and by value, see Passing Reference-Type Parameters and Reference Types.

Valores devueltosReturn Values

Los métodos pueden devolver un valor al autor de llamada.Methods can return a value to the caller. Si el tipo de valor devuelto, el tipo enumerado antes del nombre de método, no es void, el método puede devolver el valor mediante la utilización de la palabra clave 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. Una instrucción con la palabra clave return seguida de un valor que coincide con el tipo de valor devuelto devolverá este valor al autor de llamada del método.A statement with the return keyword followed by a value that matches the return type will return that value to the method caller.

El valor puede devolverse al autor de la llamada mediante valor o, a partir de C# 7.0, mediante referencia.The value can be returned to the caller by value or, starting with C# 7.0, by reference. Los valores se devuelven al autor de la llamada mediante referencia si la palabra clave ref se usa en la firma del método y sigue cada palabra clave 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. Por ejemplo, la siguiente firma del método y la instrucción return indican que el método devuelve nombres de variable estDistance mediante referencia al autor de la llamada.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;
}

La palabra clave return también detiene la ejecución del método.The return keyword also stops the execution of the method. Si el tipo de valor devuelto es void, una instrucción return sin un valor también es útil para detener la ejecución del método.If the return type is void, a return statement without a value is still useful to stop the execution of the method. Sin la palabra clave return , el método dejará de ejecutarse cuando alcance el final del bloque de código.Without the return keyword, the method will stop executing when it reaches the end of the code block. Los métodos con un tipo de valor devuelto no nulo son necesarios para usar la palabra clave return para devolver un valor.Methods with a non-void return type are required to use the return keyword to return a value. Por ejemplo, estos dos métodos utilizan la palabra clave return para devolver enteros: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;
    }
}

Para utilizar un valor devuelto de un método, el método de llamada puede usar la llamada de método en cualquier lugar; un valor del mismo tipo sería suficiente.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. También puede asignar el valor devuelto a una variable.You can also assign the return value to a variable. Por ejemplo, los dos siguientes ejemplos de código logran el mismo objetivo: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);

Usar una variable local, en este caso, result, para almacenar un valor es opcional.Using a local variable, in this case, result, to store a value is optional. La legibilidad del código puede ser útil, o puede ser necesaria si debe almacenar el valor original del argumento para todo el ámbito del método.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.

Para usar un valor devuelto mediante referencia de un método, debe declarar una variable local de tipo ref si pretende modificar su valor.To use a value returned by reference from a method, you must declare a ref local variable if you intend to modify its value. Por ejemplo, si el método Planet.GetEstimatedDistance devuelve un valor Double mediante referencia, puede definirlo como una variable local de tipo ref con código como el siguiente: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 

Devolver una matriz multidimensional de un método, M, que modifica el contenido de la matriz no es necesario si la función de llamada ha pasado la matriz a 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. Puede devolver la matriz resultante de M para obtener un estilo correcto o un flujo funcional de valores, pero no es necesario porque C# pasa todos los tipos de referencia mediante valor, y el valor de una referencia de matriz es el puntero de la matriz.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. En el método M, los cambios en el contenido de la matriz los puede observar cualquier código que tenga una referencia a la matriz, como se muestra en el ejemplo siguiente.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;
        }
    }
}

Para obtener más información, consulta return.For more information, see return.

Métodos asincrónicosAsync Methods

Mediante la característica asincrónica, puede invocar métodos asincrónicos sin usar definiciones de llamada explícitas ni dividir manualmente el código en varios métodos o expresiones lambda.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.

Si marca un método con el modificador async , puede usar el operador await en el método.If you mark a method with the async modifier, you can use the await operator in the method. Cuando el control alcanza una expresión await en el método asincrónico, el control se devuelve al autor de llamada y se progreso del método se suspende hasta que se completa la tarea esperada.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. Cuando se completa la tarea, la ejecución puede reanudarse en el método.When the task is complete, execution can resume in the method.

Nota

Un método asincrónico vuelve al autor de llamada cuando encuentra el primer objeto esperado que aún no se ha completado o cuando llega al final del método asincrónico, lo que ocurra primero.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.

Un método asincrónico puede tener un tipo de valor devuelto de Task<TResult>, Task, o nulo.An async method can have a return type of Task<TResult>, Task, or void. El tipo de valor devuelto nulo se utiliza principalmente para definir controladores de eventos, donde se requiere un tipo de valor devuelto nulo.The void return type is used primarily to define event handlers, where a void return type is required. No se puede esperar un método asincrónico que devuelve nulo, y el autor de llamada de un método con tipo de devolución nulo no puede capturar ninguna excepción producida por este.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.

En el ejemplo siguiente, DelayAsync es un método asincrónico con un tipo de valor devuelto de Task<TResult>.In the following example, DelayAsync is an async method that has a return type of Task<TResult>. DelayAsync tiene una instrucción return que devuelve un entero.DelayAsync has a return statement that returns an integer. Por lo tanto, la declaración del método de DelayAsync debe tener un tipo de valor devuelto de Task<int>.Therefore the method declaration of DelayAsync must have a return type of Task<int>. Dado que el tipo de valor devuelto es Task<int>, la evaluación de la expresión await en DoSomethingAsync genera un entero, como se demuestra en la siguiente instrucción: 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.

El método startButton_Click es un ejemplo de un método asincrónico con un tipo de valor devuelto nulo.The startButton_Click method is an example of an async method that has a return type of void. Dado que DoSomethingAsync es un método asincrónico, la tarea de la llamada a DoSomethingAsync debe esperar, como se muestra en la siguiente instrucción: 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();. El método startButton_Click debe definirse con el modificador async porque el método tiene una expresión 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

Un método aisncrónico no puede declarar ningún parámetro ref u out , pero puede llamar a los métodos que tienen estos parámetros.An async method can't declare any ref or out parameters, but it can call methods that have such parameters.

Para obtener más información sobre los métodos asincrónicos, vea Programación asincrónica con Async y Await, Flujo de control en programas asincrónicos y Tipos de valor devuelto de Async.For more information about async methods, see Asynchronous Programming with async and await, Control Flow in Async Programs, and Async Return Types.

Definiciones de cuerpos de expresiónExpression Body Definitions

Es habitual tener definiciones de método que simplemente hacen las devoluciones de forma inmediata con el resultado de una expresión, o que tienen una sola instrucción como cuerpo del método.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. Hay un acceso directo de sintaxis para definir este método mediante =>: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);  

Si el método devuelve void o si es un método asincrónico, el cuerpo del método debe ser una expresión de instrucción (igual que con las expresiones lambda).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). Para las propiedades y los indexadores, solo deben leerse, y no usa la palabra clave de descriptor de acceso get.For properties and indexers, they must be read only, and you don't use the get accessor keyword.

IteratorsIterators

Un iterador realiza una iteración personalizada en una colección, como una lista o matriz.An iterator performs a custom iteration over a collection, such as a list or an array. Un iterador utiliza la instrucción yield return para devolver cada elemento de uno en uno.An iterator uses the yield return statement to return each element one at a time. Cuando se alcanza la instrucción yield return , se recuerda la ubicación actual en el código.When a yield return statement is reached, the current location in code is remembered. La ejecución se reinicia desde esa ubicación la próxima vez que se llama el iterador.Execution is restarted from that location when the iterator is called the next time.

Llame a un iterador a partir del código de cliente mediante una instrucción foreach .You call an iterator from client code by using a foreach statement.

El tipo de valor devuelto de un iterador puede ser IEnumerable, IEnumerable<T>, IEnumeratoro IEnumerator<T>.The return type of an iterator can be IEnumerable, IEnumerable<T>, IEnumerator, or IEnumerator<T>.

Para obtener más información, consulta Iteradores.For more information, see Iterators.

Especificación del lenguaje C#C# Language Specification

Para obtener más información, consulte la Especificación del lenguaje C#.For more information, see the C# Language Specification. La especificación del lenguaje es la fuente definitiva de la sintaxis y el uso de C#.The language specification is the definitive source for C# syntax and usage.

Vea tambiénSee also