Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Instrucciones Jump:
Las instrucciones jump transfieren incondicionalmente el control. La break instrucción finaliza la instrucción oswitch instrucción de iteración más cercana. La continue instrucción inicia una nueva iteración de la instrucción de iteración más cercana. La return instrucción finaliza la ejecución de la función en la que aparece y devuelve el control al autor de la llamada. La goto instrucción transfiere el control a una instrucción marcada por una etiqueta.
Para obtener información sobre la throw instrucción que produce una excepción y también transfiere un control de transferencia incondicional, vea la sección Instrucción throw del artículo Instrucciones de control de excepciones.
Instrucción break
La break instrucción finaliza la instrucción de iteración más cercana (es decir, for, foreach, whileo do bucle) o switch instrucción . La break instrucción transfiere el control a la instrucción que sigue a la instrucción terminada, si existe.
int[] numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
foreach (int number in numbers)
{
if (number == 3)
{
break;
}
Console.Write($"{number} ");
}
Console.WriteLine();
Console.WriteLine("End of the example.");
// Output:
// 0 1 2
// End of the example.
En bucles anidados, la break instrucción finaliza solo el bucle más interno que lo contiene, como se muestra en el ejemplo siguiente:
for (int outer = 0; outer < 5; outer++)
{
for (int inner = 0; inner < 5; inner++)
{
if (inner > outer)
{
break;
}
Console.Write($"{inner} ");
}
Console.WriteLine();
}
// Output:
// 0
// 0 1
// 0 1 2
// 0 1 2 3
// 0 1 2 3 4
Cuando se usa la switch instrucción dentro de un bucle, una break instrucción al final de una sección switch transfiere el control solo fuera de la switch instrucción. El bucle que contiene la switch instrucción no se ve afectado, como se muestra en el ejemplo siguiente:
double[] measurements = [-4, 5, 30, double.NaN];
foreach (double measurement in measurements)
{
switch (measurement)
{
case < 0.0:
Console.WriteLine($"Measured value is {measurement}; too low.");
break;
case > 15.0:
Console.WriteLine($"Measured value is {measurement}; too high.");
break;
case double.NaN:
Console.WriteLine("Failed measurement.");
break;
default:
Console.WriteLine($"Measured value is {measurement}.");
break;
}
}
// Output:
// Measured value is -4; too low.
// Measured value is 5.
// Measured value is 30; too high.
// Failed measurement.
Instrucción continue
La continue instrucción inicia una nueva iteración de la instrucción de iteración más cercana (es decir, for, foreach, o whiledo bucle), como se muestra en el ejemplo siguiente:
for (int i = 0; i < 5; i++)
{
Console.Write($"Iteration {i}: ");
if (i < 3)
{
Console.WriteLine("skip");
continue;
}
Console.WriteLine("done");
}
// Output:
// Iteration 0: skip
// Iteration 1: skip
// Iteration 2: skip
// Iteration 3: done
// Iteration 4: done
Instrucción return
La return instrucción finaliza la ejecución de la función en la que aparece y devuelve el control y el resultado de la función, si existe, al autor de la llamada.
Si un miembro de función no calcula un valor, se usa la return instrucción sin expresión, como se muestra en el ejemplo siguiente:
Console.WriteLine("First call:");
DisplayIfNecessary(6);
Console.WriteLine("Second call:");
DisplayIfNecessary(5);
void DisplayIfNecessary(int number)
{
if (number % 2 == 0)
{
return;
}
Console.WriteLine(number);
}
// Output:
// First call:
// Second call:
// 5
Como se muestra en el ejemplo anterior, normalmente se usa la return instrucción sin expresión para finalizar un miembro de función al principio. Si un miembro de función no contiene la return instrucción , finaliza después de ejecutar su última instrucción.
Si un miembro de función calcula un valor, se usa la return instrucción con una expresión, como se muestra en el ejemplo siguiente:
double surfaceArea = CalculateCylinderSurfaceArea(1, 1);
Console.WriteLine($"{surfaceArea:F2}"); // output: 12.57
double CalculateCylinderSurfaceArea(double baseRadius, double height)
{
double baseArea = Math.PI * baseRadius * baseRadius;
double sideArea = 2 * Math.PI * baseRadius * height;
return 2 * baseArea + sideArea;
}
Cuando la return instrucción tiene una expresión, esa expresión debe convertirse implícitamente en el tipo de valor devuelto de un miembro de función a menos que sea asincrónico. La expresión devuelta desde una async función debe convertirse implícitamente en el argumento type de Task<TResult> o ValueTask<TResult>, lo que sea el tipo de valor devuelto de la función. Si el tipo de valor devuelto de una async función es Task o ValueTask, se usa la return instrucción sin expresión.
Devolución de referencia
De forma predeterminada, la return instrucción devuelve el valor de una expresión. Puede devolver una referencia a una variable. Los valores devueltos de referencia (o devoluciones ref) son valores que devuelve un método por referencia al autor de la llamada. Es decir, el autor de la llamada puede modificar el valor devuelto por un método y ese cambio se refleja en el estado del objeto en el método llamado. Para ello, use la return instrucción con la ref palabra clave , como se muestra en el ejemplo siguiente:
int[] xs = new int [] {10, 20, 30, 40 };
ref int found = ref FindFirst(xs, s => s == 30);
found = 0;
Console.WriteLine(string.Join(" ", xs)); // output: 10 20 0 40
ref int FindFirst(int[] numbers, Func<int, bool> predicate)
{
for (int i = 0; i < numbers.Length; i++)
{
if (predicate(numbers[i]))
{
return ref numbers[i];
}
}
throw new InvalidOperationException("No element satisfies the given condition.");
}
Un valor devuelto de referencia permite a un método devolver una referencia a una variable, en lugar de un valor, de nuevo a un autor de llamada. Después, el autor de la llamada puede tratar la variable devuelta como si se devolva por valor o por referencia. El autor de la llamada puede crear una nueva variable que sea en sí misma una referencia al valor devuelto, denominada referencia local. Un valor devuelto de referencia significa que un método devuelve una referencia (o un alias) a alguna variable. El ámbito de esa variable debe incluir el método . La duración de esa variable debe extenderse más allá del retorno del método . Las modificaciones en el valor devuelto del método por el llamador se realizan en la variable devuelta por el método .
Declarar que un método devuelve un valor devuelto de referencia indica que el método devuelve un alias a una variable. La intención de diseño suele ser que la llamada al código accede a esa variable a través del alias, incluido para modificarla. Los métodos que devuelven por referencia no pueden tener el tipo voidde valor devuelto .
Para que el autor de la llamada modifique el estado del objeto, el valor devuelto de referencia debe almacenarse en una variable que se define explícitamente como una variable de referencia.
El ref valor devuelto es un alias para otra variable en el ámbito del método llamado. Puede interpretar cualquier uso de la devolución ref como mediante la variable que alias tiene:
- Al asignar su valor, va a asignar un valor a la variable que alias.
- Al leer su valor, está leyendo el valor de la variable que alias.
- Si lo devuelve por referencia, va a devolver un alias a esa misma variable.
- Si se pasa a otro método por referencia, se pasa una referencia a la variable que alias.
- Al crear un alias local ref , se crea un nuevo alias en la misma variable.
Una devolución ref debe ser ref-safe-context para el método de llamada. Eso significa:
- El valor devuelto debe tener una duración que se extienda más allá de la ejecución del método . En otras palabras, no puede ser una variable local en el método que la devuelve. Puede ser una instancia o un campo estático de una clase, o puede ser un argumento pasado al método . Si se intenta devolver una variable local, se genera el error del compilador CS8168, "No se puede devolver "obj" local local por referencia porque no es una referencia local".
- El valor devuelto no puede ser el literal
null. Un método con una devolución de referencia puede devolver un alias a una variable cuyo valor es actualmente elnullvalor (no fundamentado) o un tipo de valor que acepta valores NULL para un tipo de valor. - El valor devuelto no puede ser una constante, un miembro de enumeración, el valor devuelto por valor de una propiedad o un método de o
classstruct.
Además, no se permiten valores devueltos de referencia en métodos asincrónicos. Un método asincrónico puede devolver antes de que haya finalizado la ejecución, mientras que su valor devuelto sigue siendo desconocido.
Un método que devuelve un valor devuelto de referencia debe:
- Incluya la palabra clave ref delante del tipo de valor devuelto.
- Cada instrucción return del cuerpo del método incluye la palabra clave ref delante del nombre de la instancia devuelta.
En el ejemplo siguiente se muestra un método que satisface esas condiciones y devuelve una referencia a un Person objeto denominado p:
public ref Person GetContactInformation(string fname, string lname)
{
// ...method implementation...
return ref p;
}
Este es un ejemplo de devolución de referencia más completo, que muestra tanto la firma del método como el cuerpo del método.
public static ref int Find(int[,] matrix, Func<int, bool> predicate)
{
for (int i = 0; i < matrix.GetLength(0); i++)
for (int j = 0; j < matrix.GetLength(1); j++)
if (predicate(matrix[i, j]))
return ref matrix[i, j];
throw new InvalidOperationException("Not found");
}
El método llamado también puede declarar el valor devuelto como ref readonly para devolver el valor por referencia y exigir que el código de llamada no pueda modificar el valor devuelto. El método de llamada puede evitar copiar el valor devuelto almacenando el valor en una variable de referencia local ref readonly .
En el ejemplo siguiente se define una Book clase que tiene dos String campos y AuthorTitle . También define una BookCollection clase que incluye una matriz privada de Book objetos. Los objetos de libro individuales se devuelven por referencia llamando a su GetBookByTitle método .
public class Book
{
public string Author;
public string Title;
}
public class BookCollection
{
private Book[] books = { new Book { Title = "Call of the Wild, The", Author = "Jack London" },
new Book { Title = "Tale of Two Cities, A", Author = "Charles Dickens" }
};
private Book nobook = null;
public ref Book GetBookByTitle(string title)
{
for (int ctr = 0; ctr < books.Length; ctr++)
{
if (title == books[ctr].Title)
return ref books[ctr];
}
return ref nobook;
}
public void ListBooks()
{
foreach (var book in books)
{
Console.WriteLine($"{book.Title}, by {book.Author}");
}
Console.WriteLine();
}
}
Cuando el autor de la llamada almacena el valor devuelto por el GetBookByTitle método como local ref, los cambios que realiza el autor de la llamada en el valor devuelto se reflejan en el objeto, como se muestra en el BookCollection ejemplo siguiente.
var bc = new BookCollection();
bc.ListBooks();
ref var book = ref bc.GetBookByTitle("Call of the Wild, The");
if (book != null)
book = new Book { Title = "Republic, The", Author = "Plato" };
bc.ListBooks();
// The example displays the following output:
// Call of the Wild, The, by Jack London
// Tale of Two Cities, A, by Charles Dickens
//
// Republic, The, by Plato
// Tale of Two Cities, A, by Charles Dickens
Instrucción goto
La goto instrucción transfiere el control a una instrucción marcada por una etiqueta, como se muestra en el ejemplo siguiente:
var matrices = new Dictionary<string, int[][]>
{
["A"] =
[
[1, 2, 3, 4],
[4, 3, 2, 1]
],
["B"] =
[
[5, 6, 7, 8],
[8, 7, 6, 5]
],
};
CheckMatrices(matrices, 4);
void CheckMatrices(Dictionary<string, int[][]> matrixLookup, int target)
{
foreach (var (key, matrix) in matrixLookup)
{
for (int row = 0; row < matrix.Length; row++)
{
for (int col = 0; col < matrix[row].Length; col++)
{
if (matrix[row][col] == target)
{
goto Found;
}
}
}
Console.WriteLine($"Not found {target} in matrix {key}.");
continue;
Found:
Console.WriteLine($"Found {target} in matrix {key}.");
}
}
// Output:
// Found 4 in matrix A.
// Not found 4 in matrix B.
Como se muestra en el ejemplo anterior, puede usar la goto instrucción para salir de un bucle anidado.
Sugerencia
Al trabajar con bucles anidados, considere la posibilidad de refactorizar bucles independientes en métodos independientes. Esto puede dar lugar a un código más sencillo y legible sin la goto instrucción .
También puede usar la goto instrucción en la switch instrucción para transferir el control a una sección switch con una etiqueta de mayúsculas y minúsculas constantes, como se muestra en el ejemplo siguiente:
using System;
public enum CoffeeChoice
{
Plain,
WithMilk,
WithIceCream,
}
public class GotoInSwitchExample
{
public static void Main()
{
Console.WriteLine(CalculatePrice(CoffeeChoice.Plain)); // output: 10.0
Console.WriteLine(CalculatePrice(CoffeeChoice.WithMilk)); // output: 15.0
Console.WriteLine(CalculatePrice(CoffeeChoice.WithIceCream)); // output: 17.0
}
private static decimal CalculatePrice(CoffeeChoice choice)
{
decimal price = 0;
switch (choice)
{
case CoffeeChoice.Plain:
price += 10.0m;
break;
case CoffeeChoice.WithMilk:
price += 5.0m;
goto case CoffeeChoice.Plain;
case CoffeeChoice.WithIceCream:
price += 7.0m;
goto case CoffeeChoice.Plain;
}
return price;
}
}
Dentro de la switch instrucción , también puede usar la instrucción goto default; para transferir el control a la sección switch con la default etiqueta .
Si una etiqueta con el nombre especificado no existe en el miembro de función actual o si la goto instrucción no está dentro del ámbito de la etiqueta, se produce un error en tiempo de compilación. Es decir, no se puede usar la goto instrucción para transferir el control fuera del miembro de función actual ni a ningún ámbito anidado.
Especificación del lenguaje C#
Para más información, vea las secciones siguientes de la Especificación del lenguaje C#: