c# - 在循环内与循环外使用 IF 语句

标签 c# .net

我有一个带有嵌套嵌套循环(总共四个循环)的程序。我有一个 bool 变量,我想影响最深循环和第一个嵌套循环中的代码。我的困境是,我真的不想将 if else 语句放入循环中,因为我认为每次迭代都会使用额外的时间来检查 bool 值的状态来检查语句,而且我知道 bool 值的状态不会循环开始时更改。这让我认为将 if else 语句放在循环之外并稍微更改我的循环代码会更好,但是,这看起来也很乱,因为有很多重复的代码。

有一个我认为可能有用但我几乎没有使用经验的东西是委托(delegate),我可以简单地将一些代码放在一个方法中然后创建一个委托(delegate),这取决于我可以分配的 betterColor 的状态事先用不同的代码委托(delegate)方法,但这看起来也很乱。

以下是我试图避免的,因为我认为它可能会减慢我的算法:

for (short y = 0; y < effectImage.Height; y++)
{
    int vCalc = (y <= radius) ? 0 : y - radius;

    for (short x = 0; x < effectImage.Width; x++)
    {
        int red = 0, green = 0, blue = 0;
        short kArea = 0;

        for (int v = vCalc; v <= y + radius && v < effectImage.Height; v++)
        {
            int calc = calcs[(y - v) + radius];
            for (int h = (x <= calc || calc < 0) ? 0 : x - calc; h <= x + calc && h < effectImage.Width; h++)
            {
                if (betterColor == true)
                {
                    red += colorImage[h, v].R * colorImage[h, v].R;
                    green += colorImage[h, v].G * colorImage[h, v].G;
                    blue += colorImage[h, v].B * colorImage[h, v].G;
                    kArea++;
                }
            }
        }

        if (betterColor == true)
            effectImage.SetPixel(x, y, Color.FromArgb(red / kArea, green / kArea, blue / kArea));
        else
            effectImage.SetPixel(x, y, Color.FromArgb(Convert.ToInt32(Math.Sqrt(red / kArea)), Convert.ToInt32(Math.Sqrt(green / kArea)), Convert.ToInt32(Math.Sqrt(blue / kArea))));
    }

    if (y % 4 == 0) // Updates the image on screen every 4 y pixels calculated.
    {
        image.Image = effectImage;
        image.Update();
    }
}

这是我的代码现在的样子:

if (betterColor == true)
{
    for (short y = 0; y < effectImage.Height; y++)
    {
        int vCalc = (y <= radius) ? 0 : y - radius;

        for (short x = 0; x < effectImage.Width; x++)
        {
            int red = 0, green = 0, blue = 0;
            short kArea = 0;

            for (int v = vCalc; v <= y + radius && v < effectImage.Height; v++)
            {
                int calc = calcs[(y - v) + radius];
                for (int h = (x <= calc || calc < 0) ? 0 : x - calc; h <= x + calc && h < effectImage.Width; h++)
                {
                    red += colorImage[h, v].R * colorImage[h, v].R;
                    green += colorImage[h, v].G * colorImage[h, v].G;
                    blue += colorImage[h, v].B * colorImage[h, v].G;
                    kArea++;
                }
            }

            effectImage.SetPixel(x, y, Color.FromArgb(Convert.ToInt32(Math.Sqrt(red / kArea)), Convert.ToInt32(Math.Sqrt(green / kArea)), Convert.ToInt32(Math.Sqrt(blue / kArea))));
        }

        if (y % 4 == 0) // Updates the image on screen every 4 y pixels calculated.
        {
            image.Image = effectImage;
            image.Update();
        }
    }
}
else
{
    for (short y = 0; y < effectImage.Height; y++)
    {
        int vCalc = (y <= radius) ? 0 : y - radius;

        for (short x = 0; x < effectImage.Width; x++)
        {
            int red = 0, green = 0, blue = 0;
            short kArea = 0;

            for (int v = vCalc; v <= y + radius && v < effectImage.Height; v++)
            {
                int calc = calcs[(y - v) + radius];
                for (int h = (x <= calc || calc < 0) ? 0 : x - calc; h <= x + calc && h < effectImage.Width; h++)
                {
                    red += colorImage[h, v].R;
                    green += colorImage[h, v].G;
                    blue += colorImage[h, v].B;
                    kArea++;
                }
            }

            effectImage.SetPixel(x, y, Color.FromArgb(red / kArea, green / kArea, blue / kArea));
        }

        if (y % 4 == 0) // Updates the image on screen every 4 y pixels calculated.
        {
            image.Image = effectImage;
            image.Update();
        }
    }
}

就代码的作用而言,它是一个使用圆形内核的框模糊。

最佳答案

if 移出循环并有效地复制整个循环代码并不值得。所以如果你有这样的代码:

for (i …)
{
    if (something)
        DoX(i);
    else
        DoY(i);
}

那么你不应该用这个替换它:

if (something)
{
    for (i …)
        DoX(i);
}
else
{
    for (i …)
        DoY(i);
}

这样做只会使代码很多更难阅读和维护。首先需要弄清楚的是,这实际上是针对每种情况执行的相同代码(除了那一点微小的差异),一旦您需要更改循环的任何内容,就很难维护,因为您需要确保正确编辑这两种情况。

虽然在理论上,执行单次检查与执行 N 次检查显然更快,但在实践中,这并不重要。依赖常量 bool 值的 If 分支非常快,因此如果您在循环外计算条件(在您的情况下 betterColor 设置在循环外),那么性能差异将不会很明显根本。此外,branch prediction通常会确保在这些情况下完全没有区别

所以不,不要那样重写代码。保持更容易理解的方式。

一般来说,无论如何您都应该避免这些微优化。您的算法很可能有慢得多的部分,这些部分与整体性能的相关性比像这样的小结构要大得多。因此,专注于那些已经非常快的小事情不会帮助您加快整体执行速度。你应该只优化你代码中的实际性能瓶颈,分析器显示存在性能问题或优化该代码将积极提高你的性能。除非您确实需要它(在大多数情况下您不会),否则请远离使代码可读性降低的优化。

关于c# - 在循环内与循环外使用 IF 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38741599/

相关文章:

c# - 如何使用 Sharepoint Web 服务从 .NET 获取文档列表?

.net - 比较两个 SQL 脚本并获取更改脚本

c# - MEF 组合问题,多线程

.net - 如何克隆动画画笔?

c# - MSMQ CreateCursor NullReferenceException 异常

c# - 如何有效地拥有与 WPF 控件像素匹配的 WritableBitmap 1 :1?

c# - 事件处理程序不再触发

c# - .net 安装程序在安装时添加 mysql 数据库表

c# - txt文件作为配置文件

c# - 调整表单大小并加载控件