C# 中break、continue、return、goto 跳转语句的使用

总目录


前言

介绍 C#中的breakcontinuereturngoto 四种跳转语句。


一、概述

  • 跳转语句无条件转移控制。
  • break 语句将终止最接近的封闭迭代语句或 switch 语句。
  • continue 语句启动最接近的封闭迭代语句的新迭代。
  • return 语句终止它所在的函数的执行,并将控制权返回给调用方。
  • goto 语句将控制权转交给带有标签的语句。

迭代语句:使用 for、foreach、do 和 while 的语句

二、break 语句(中断语句)

1. 介绍

  • break 语句:将终止最接近的封闭迭代语句(即 for、foreach、while 或 do 循环)或 switch 语句。
  • break 语句将控制权转交给已终止语句后面的语句(若有)。

简单说: 在loop 中使用 break 将跳出整个循环,在switch 中使用break 将跳出switch 语句 ,然后执行后面的业务逻辑

2. 使用

        static void Main(string[] args)
        {
            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.
        }

上例中,当number == 3 的时候 就使用break 跳出了循环,因此只会输出0 1 2

        static void Main(string[] args)
        {
            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
        }

上例中,使用了双层for 的嵌套循环。在嵌套循环中,break 语句仅终止包含它的最内部循环。

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.

上例中,在循环内使用 switch 语句时,switch 节末尾的 break 语句仅从 switch 语句中转移控制权。 包含 switch 语句的循环不受影响

二、continue 语句(继续语句)

1. 介绍

  • continue 语句启动最接近的封闭迭代语句(即 for、foreach、while 或 do 循环)的新迭代

简单说:跳出本轮循环,开始下一轮循环

2. 使用

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

三、return 语句(返回语句)

1. 介绍

  • return 语句终止它所在的函数的执行,并将控制权和函数结果(若有)返回给调用方。

简单说:方法中使用 return,第一先终止执行(不再执行后面的代码),有返回值则返回 返回值,没有返回值,作用仅为终止执行

2. 使用

如果函数成员不计算值,则使用不带表达式的 return 语句

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

使用带表达式的 return 语句

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

如果 return 语句具有表达式,该表达式必须可隐式转换为函数成员的返回类型,除非它是异步的。 从 async 函数返回的表达式必须隐式转换为 Task<TResult> 或 ValueTask<TResult> 类型参数,以函数的返回类型为准。 如果 async 函数的返回类型为 Task 或 ValueTask,则使用不带表达式的 return 语句。

三、goto 语句

1. 介绍

  • goto 语句将控制权转交给带有标签的语句
  • 使用goto ,可以跳出 嵌套循环

简单说:代码跳转到 带有标签的地方 开始执行

2. 使用

  • 下面案例中,定义了一个 Found: 标签,然后使用goto 跳转到Found 标签处
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.
  • 还可使用 switch 语句中的 goto 语句将控制权移交到具有常量大小写标签的 switch 节,如以下示例所示:
    public enum CoffeeChoice
    {
        Plain,
        WithMilk,
        WithIceCream,
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            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;
        }
    }

在 switch 语句中,还可使用语句 goto default; 将控制权转交给带 default 标签的 switch 节。

3. 注意事项

  • 可读性:goto语句会使代码流程难以追踪,特别是在复杂的代码结构中。因此,尽量避免使用goto,改用循环和条件语句来管理代码流程。

  • 避免嵌套:尽量避免在深层嵌套的代码块中使用goto,因为这会使代码更加混乱和难以调试。

  • 避免跳转到循环或条件语句内:通常不建议将goto语句用于跳转到循环或条件语句内部,因为这可能会导致不可预测的行为。

  • 作用域问题:goto语句不能跨方法或块作用域跳转。它只能在当前方法或块内跳转。

  • 结构化编程:尽量使用结构化编程技术(如循环、条件语句、方法调用等)来替代goto,以保持代码的可读性和可维护性。

  • 替代方案

    • 循环和条件语句:使用for、while、if-else等控制结构来替代goto。
    • 方法调用:将复杂的逻辑拆分成多个方法,通过方法调用来控制流程。
    • 异常处理:在需要跳出多层嵌套结构时,可以考虑使用异常处理机制(虽然这也不是最佳实践,但在某些情况下可能是可行的)。

四、跳转语句与try语句

  • 跳转语句的执行因存在干预 try 语句而变得复杂。
  • 在没有 try的情况下,跳转语句无条件地将控制权从跳转语句转移到其目标。
  • 在存在此类干预 try 语句的情况下,执行更为复杂。
    • 如果 jump 语句退出一个或多个 try 具有关联 finally 块的块,则控件最初将传输到 finally 最 try 内部语句的块。 当控件到达块的 finally 终点时,控件将 finally 传输到下一个封闭 try 语句的块。 此过程将重复执行, finally 直到执行所有干预 try 语句的块。
class Test
{
    static void Main()
    {
        while (true)
        {
            try
            {
                try
                {
                    Console.WriteLine("Before break");
                    break;
                }
                finally
                {
                    Console.WriteLine("Innermost finally block");
                }
            }
            finally
            {
                Console.WriteLine("Outermost finally block");
            }
        }
        Console.WriteLine("After break");
    }
}
Before break
Innermost finally block
Outermost finally block
After break

结语

回到目录页:C# 知识汇总
希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。


参考资料
跳转语句
13.10 Jump 语句
C#中的goto语句:使用方法、注意事项及替代方案

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鲤籽鲲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值