开关箱内有条件断路

本文关键字:断路 有条件 开关箱 | 更新日期: 2023-09-27 18:27:59

我想知道是否有可能在C#中的switch语句中有条件地突破case。以下面的例子为例。

MediaStream photoMediaStream = null;
switch (photoSize)
{
    case PhotoSize.Normal:
        if (imageWidth >= NormalWidth && imageWidth % NormalWidth == 0)
        {
            photoMediaStream = photoMedia.GetStream(new MediaOptions {Width = NormalWidth});
            break;
        }
    case PhotoSize.Small:
        if (imageWidth >= SmallWidth && imageWidth % SmallWidth == 0)
        {
            photoMediaStream = photoMedia.GetStream(new MediaOptions {Width = SmallWidth});
            break;
        }
    case PhotoSize.Thumb:
        if (imageWidth >= ThumbWidth && imageWidth % ThumbWidth == 0)
        {
            photoMediaStream = photoMedia.GetStream(new MediaOptions {Width = ThumbWidth});
            break;
        }
}

基本上,如果条件为真,我想做点什么,然后突破switch语句,但如果不是,我只想进入下一个情况。

开关箱内有条件断路

由于不能隐式地进入下一个案例,因此必须使用goto语句显式执行。这是少数可以接受使用此语句的情况之一。。。

MediaStream photoMediaStream = null;
switch (photoSize)
{
    case PhotoSize.Normal:
        if (imageWidth >= NormalWidth && imageWidth % NormalWidth == 0)
        {
            photoMediaStream = photoMedia.GetStream(new MediaOptions {Width = NormalWidth});
            break;
        }
        goto case PhotoSize.Small;
    case PhotoSize.Small:
        if (imageWidth >= SmallWidth && imageWidth % SmallWidth == 0)
        {
            photoMediaStream = photoMedia.GetStream(new MediaOptions {Width = SmallWidth});
            break;
        }
        goto case PhotoSize.Thumb;
    case PhotoSize.Thumb:
        if (imageWidth >= ThumbWidth && imageWidth % ThumbWidth == 0)
        {
            photoMediaStream = photoMedia.GetStream(new MediaOptions {Width = ThumbWidth});
            break;
        }
}

无论如何,使用if语句重构它可能会更好:

MediaStream GetPhotoMediaStream(PhotoSize photoSize, /* whatever parameters you need... */)
{
    if (photoSize == PhotoSize.Normal)
    {
        if (imageWidth >= NormalWidth && imageWidth % NormalWidth == 0)
        {
            return photoMedia.GetStream(new MediaOptions {Width = NormalWidth});
        }
        photoSize = PhotoSize.Small;
    }
    if (photoSize == PhotoSize.Small)
    {
        if (imageWidth >= SmallWidth && imageWidth % SmallWidth == 0)
        {
            return photoMedia.GetStream(new MediaOptions {Width = SmallWidth});
        }
        photoSize = PhotoSize.Thumb;
    }
    if (photoSize == PhotoSize.Thumb)
    {
        if (imageWidth >= ThumbWidth && imageWidth % ThumbWidth == 0)
        {
            return photoMedia.GetStream(new MediaOptions {Width = ThumbWidth});
        }
    }
    return null;
}

否,C#不允许在开关中发生故障,除非在两种情况之间没有代码。参见C#规范第8.7.2点:

如果开关部分的语句列表的终点是可到达的,则会发生编译时错误。

您可以使用goto case转到其他情况。

switch (photoSize)
{
    case PhotoSize.Normal:
        if (imageWidth >= NormalWidth && imageWidth % NormalWidth == 0)
        {
            photoMediaStream = photoMedia.GetStream(new MediaOptions {Width = NormalWidth});
            break;
        }
        goto case PhotoSize.Small;
    case PhotoSize.Small:
        if (imageWidth >= SmallWidth && imageWidth % SmallWidth == 0)
        {
            photoMediaStream = photoMedia.GetStream(new MediaOptions {Width = SmallWidth});
            break;
        }
        goto case PhotoSize.Thumb;
    case PhotoSize.Thumb:
        if (imageWidth >= ThumbWidth && imageWidth % ThumbWidth == 0)
        {
            photoMediaStream = photoMedia.GetStream(new MediaOptions {Width = ThumbWidth});
            break;
        }
        break;
    }

C#不支持当任何代码介于两者之间时的贯穿大小写标签(请参阅C#中的Switch语句贯穿)
因此,您当然可以有条件地断开-然而,无论如何,您也必须在每个块的末尾断开;-)

只需使用一些if。

不,这是不可能的,因为如果不满足if条件,程序应该从一个案例流到下一个案例(这在C#中是不允许的)。

来自MSDN:

所选部分中语句列表的执行以第一个语句,然后继续执行语句列表,通常直到达到跳转语句,例如break、goto case,return或throw。此时,控制权将转移到switch语句或另一个大小写标签。

与C++不同,C#不允许从一个开关继续执行下一节

如果您需要在函数中对代码的执行进行条件化,请不要使用switch/case,而是使用if语句链。当您想要"中断"执行流时,请使用return

正如其他人所提到的,C#不允许失败。它确实允许堆放箱子,但这对你没有帮助。但是,您可以使用if条件之外的goto语句将控制权显式转移到另一个(或者在您的情况下,是下一个)情况。

在有人说‘天哪!!eww。。。加油,我必须补充一点,很少有案例值得使用gotos。这似乎是其中之一。只要不被滥用,gotos就没有本质上的错误

将"break"置于If条件之外。。

MediaStream photoMediaStream = null;
switch (photoSize)
{
   case PhotoSize.Normal:
    if (imageWidth >= NormalWidth && imageWidth % NormalWidth == 0)
    {
        photoMediaStream = photoMedia.GetStream(new MediaOptions {Width = NormalWidth});
    }
 break;
 case PhotoSize.Small:
    if (imageWidth >= SmallWidth && imageWidth % SmallWidth == 0)
    {
        photoMediaStream = photoMedia.GetStream(new MediaOptions {Width = SmallWidth});
    }
break;
case PhotoSize.Thumb:
    if (imageWidth >= ThumbWidth && imageWidth % ThumbWidth == 0)
    {
        photoMediaStream = photoMedia.GetStream(new MediaOptions {Width = ThumbWidth});
    }
break;
 }