Break

终止 for、foreach、while 和 do 迭代循环,或者 switch。break 将仅终止其所在的循环或选择。若有循环外或选择外语句,控制权交给终止语句后面的语句。


最简单的

        private static void FF基础的Break ( )
            {
            int [ ] Zhss = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
            foreach ( int z in Zhss )
                {
                if ( z == 6 )
                    {
                    break;
                    }
                Console . Write ( $"{z}," );
                }
            Console . WriteLine ( );
            Console . WriteLine ( "例程结束。" );
            }

输出结果:
1,2,3,4,5,

例程结束。

你可以把代码中的 ( z == 6 ) 中的 6 改为任意大于 1 且小于 9 的自然数,以输出它们。break 语句将在 z 等于指定的数值时退出 foreach 循环。


嵌套的循环

当循环中包括循环时,break 只终止包含它的循环。例如:

        private static void FF嵌套的break ( )
            {
            for ( int Q = 1 ; Q < 10 ; Q++ )
                {
                for ( int H = 1 ; H < 10 ; H++ )
                    {
                    if ( H > Q )
                        {
                        break; // 终止 H 循环,继续 Q 循环
                        }
                    Console . Write ( $"{H}\t" );
                    }
                Console . WriteLine ( );
                }
            }

例程中的 break 只终止 H 循环,继续 Q 循环。


终止 switch

下面这个例程是个伪代码,意即当你的屋里温度不适宜的时候的空调启动过程:

double 室温 = 空调 . FF获取室温 ( );
switch ( 室温 )
    {
    case < 15:
        空调 . 升温 ( );
        break;
    case > 26:
        空调 . 降温 ( );
        break;
    case double . NaN:
        Console . WriteLine ( "空调坏了!" );
        break;
    default:
        Console . WriteLine ( $"室内温度:{室温}" );
        break;
    }

假设这是一个空调的控制程序(具有完备的启动程序和温度测试程序),那么室温在 15℃ 以下会升温,26℃ 以上会降温。否则只是显示室温而不工作。

break(或其他跳转语句)只是在完成 switch 选择的过程后退出该选择过程,如果没有跳转语句,C# 不知道如何退出去,将会提示 CS0163 编译错误,必须使用 break、return、goto、continue 或 throw 等关键字终止该节。否则 C# 会认为 switch 贯穿下一个条件了。

continue

当某个循环(for、foreach、while 或 do)遇到 continue 语句,当前循环是被抛弃的,但要继续下一次循环。例如:

for ( int z = 1 ;  z <= 15 ;  z++ )
    {
        Console . Write ( $"操作数:{z}" )
        if ( z % 5 = 0 )
            {
                Console . WriteLine ( $"5 的倍数:{z}" );
            }
        else
            {
                Console . WriteLine ( $"不是 5 的倍数:{z}" );
                continue;
            }

上例中的 continue 其实没用。但当你的循环需要大量的操作而其实无效时,continue 可以节省大量工作时间。

retrun

return 是返回结果的指令。它会立刻退出当前代码所在的函数、方法等,把控制权交还给调用方,并且若是有函数结果,一并还给调用方。
例如,下面的函数将返回一个圆的面积,或者返回零:

    public class YuanLei ( double 半径 )
        {
        private readonly double _半径;

        public double SX面积 ( )
            {
            return Math . PI * ( Math . Pow ( _半径 , 2 ) );
            }
        }

下面是没有返回值的 retrun:

        static void FF必要的 ( int 数 )
            {
            if ( 数 % 2 == 0 )
                {
                return;
                }
            Console . WriteLine ( 数 );
            }

调用下列代码:

            Console . Write ( $"第一次调用:" );
            FF必要的 ( 5 );
            Console . Write ( $"第二次调用:" );
            FF必要的 ( 6 );

将产生下列输出:
第一次调用:5
第二次调用:

意即第一次由于参数不是个偶数,而输出数本身,第二次参数是个偶数,则输出 null。
如果 return 语句具有表达式,该表达式必须可隐式转换为函数成员的返回类型,除非它是异步的。 从 async 函数返回的表达式必须隐式转换为 Task<TResult> 或 ValueTask<TResult> 类型参数,以函数的返回类型为准。 如果 async 函数的返回类型为 Task 或 ValueTask,则使用不带表达式的 return 语句。


引用返回

默认情况下,return 语句返回表达式的值。可以返回对变量的引用。引用返回值(或 ref 返回值)是由方法按引用向调用方返回的值。即是调用方可以修改方法所返回的值,此更改反映在所调用方法中的对象的状态中。为此,请使用带 ref 关键字的 return 语句。
借助引用返回值,方法可以将对变量的引用(而不是值)返回给调用方。然后,调用方可以选择将返回的变量视为按值返回或按引用返回。调用方可以新建称为引用本地的变量,其本身就是对返回值的引用。引用返回值是指,方法返回对某变量的引用(或别名)。相应变量的作用域必须包括方法。相应变量的生存期必须超过方法的返回值。调用方对方法的返回值进行的修改应用于方法返回的变量。
如果声明方法返回引用返回值,表明方法返回变量别名。设计意图通常是让调用代码通过别名访问此变量(包括修改它)。方法的引用返回值不得包含返回类型 void。
为方便调用方修改对象的状态,引用返回值必须存储在被显式定义为 reference 变量的变量中。
ref 返回值是被调用方法范围中另一个变量的别名。 可以将引用返回值的所有使用都解释为,使用它取别名的变量:

  • 分配值时,就是将值分配到它取别名的变量。
  • 读取值时,就是读取它取别名的变量的值。
  • 如果以引用方式返回它,就是返回对相同变量所取的别名。
  • 如果以引用方式将它传递到另一个方法,就是传递对它取别名的变量的引用。
  • 如果返回引用本地别名,就是返回相同变量的新别名。

引用返回必须是调用方法的 ref-safe-context。也就是说:

  • 返回值的生存期必须长于方法执行时间。换言之,它不能是返回自身的方法中的本地变量。它可以是实例或类的静态字段,也可是传递给方法的参数。尝试返回局部变量将生成编译器错误 CS8168:“无法按引用返回局部 "obj",因为它不是 ref 局部变量”。
  • 返回值不得为文本 null。 使用引用返回值的方法可以返回值当前为 null(未实例化)或可为空的值类型的变量别名。
  • 返回值不得为常量、枚举成员、通过属性的按值返回值或 class/struct 方法。
    此外,禁止对异步方法使用引用返回值。异步方法可能会在执行尚未完成时就返回值,尽管返回值仍未知。

返回引用返回值的方法必须:

  • 在返回类型前面有 ref 关键字。
  • 方法主体中的每个 return 语句都在返回实例的名称前面有 ref 关键字。

下面定义了书(Shu)类,仅包含书名和作者两项:

/// <summary>
/// 我的书类
/// </summary>
public class Shu
{
    public string? 书名 , 作者;
    public override string ToString ( )
    {
        return $"{书名},{作者}";
    }
}

下面定义了我的书类(书名和作者都是瞎编的,唯一的“彡”是我的外号)

public class 我的书
    {
    private Shu [ ] MB = [ new Shu { 书名 = "水瓶传" , 作者 = "施大娘" } , new Shu { 书名 = "五胡演义" , 作者 = "彡"} ];
    private Shu Mei = null;
    public ref Shu FF自书名获取书籍 ( string 书名 )
        {
        for ( int z = 0 ; z < MB . Length ; z++ )
            {
            if ( 书名 == MB [ z ] . 书名 )
                {
                return ref MB [ z ];
                }
            }
        return ref Mei;
        }
        public void FF书籍列表 ( )
            {
            foreach ( Shu S in MB )
            {
                Console . WriteLine ( $"{S . 书名},作者:{S . 作者}" );
            }
            Console . WriteLine ( );
            }
        }

执行下列操作后:

            var Shus = new 我的书 ( );
            Shus . FF书籍列表 ( );

显示结果:
水瓶传,作者:施大娘
五胡演义,作者:彡
执行下列操作后:

ref var S = ref Shus . FF自书名获取书籍 ( "五胡演义" );
if ( S != null )
    {
    S = new Shu { 书名 = "我的地啊" , 作者 = "翔大爷" };
    }
    Shus . FF书籍列表 ( );

显示结果:
水瓶传,作者:施大娘
我的地啊,作者:翔大爷

代码将 S 描述为我的书籍里面找到的书名为《五胡演义》的,并改成《我的地啊》,作者为“翔大爷”(我儿子)。代码引用了调用方对返回值的修改。

goto

当年玩 Basic 的时候,很烦标签。Basic 自称太不结构化了。不知道为啥 C# 依然留着这个……
首先声明一个词典(Dictionary),表明你学习成绩在排名上的变化:

Dictionary< string , int [ ] [ ] > 学期排名 = new ( )
    {
    ["上学期"] = [ [1, 2, 3, 4], [4, 3, 2, 1] ],
    ["下学期"] = [ [5, 6, 7, 8], [8, 7, 6, 5] ],
    };

然后检查名次:

    private static void FF检查名次 ( Dictionary< string , int [ ] [ ] > 查找名次 , int 名次 )
   {
       foreach ( var (YCH, Zhi) in 查找名次 )
            {
            for ( int H = 0 ; H < Zhi . Length ; H++ )
                {
                for ( int L = 0 ; L < Zhi [ H ] . Length ; L++ )
                    {
                    if ( Zhi [ H ] [ L ] == 名次 )
                        {
                        goto 找到啦; // 转移到“找到啦”
                        }
                    }
                }
            Console . WriteLine ( $"在 {YCH} 中找不到你的名次 {名次}" );
            continue;

            找到啦: // 这是找到啦的转移位置
            Console . WriteLine ( $"在 {YCH} 中找到你的名次 {名次}" );
                }
            }

C# FF检查名次 ( 学期排名 , 4 ); 的结果为:
在 上学期 中找到你的名次 4
在 下学期 中找不到你的名次 4
在 switch 中,可以使用 goto default; 将控制权转移到 default 标签的 switch 节。
如果当前函数成员中不存在具有给定名称的标签,或者 goto 语句不在标签范围内,则会出现编译时错误。 也就是说,你不能使用 goto 语句将控制权从当前函数成员转移到任何嵌套范围。


兔子码农
2 声望1 粉丝

一个酒晕子