C# 重构相关条件而不进行组合

C# 重构相关条件而不进行组合,c#,.net,refactoring,conditional,pixel,C#,.net,Refactoring,Conditional,Pixel,我有一个像素/位置,我们在图上称之为4,4。 我试图重构一个函数,检查周围的像素是否在所有8个方向(对角线、水平和垂直方向)上都符合某个标准,如果它符合该标准,则执行一个具有返回值的公共操作 例如: int weight=0; if (CheckWeight(new Point(4,4)) == true) weight +=100; if (CheckWeight(new Point(4,5)) == true) weight +=10; if (CheckWeight(new

我有一个像素/位置,我们在图上称之为4,4。 我试图重构一个函数,检查周围的像素是否在所有8个方向(对角线、水平和垂直方向)上都符合某个标准,如果它符合该标准,则执行一个具有返回值的公共操作

例如:

int weight=0;
if (CheckWeight(new Point(4,4)) == true)
    weight +=100;
if (CheckWeight(new Point(4,5)) == true)
    weight +=10;
if (CheckWeight(new Point(4,3)) == true)
    weight +=10;
if (CheckWeight(new Point(5,5)) == true)
    weight +=10;
if (CheckWeight(new Point(3,3)) == true)
    weight +=10;
if (CheckWeight(new Point(3,4)) == true)
    weight +=10;
if (CheckWeight(new Point(5,4)) == true)
    weight +=10;
if (CheckWeight(new Point(5,3)) == true)
    weight +=10;
if (CheckWeight(new Point(3,5)) == true)
    weight +=10;
有没有重构这些的好方法,所以如果我必须在这里改变某些东西,比如我调用的函数来检查重量,或者我检查的条件,或者重量增加,那么我不会重复我的工作8次

我认识的其他程序员已经建议将它们合并到一个检查下,这显然是我做不到的,因为它可能会满足其中的3个检查,这次给我30的权重,下次给我5个检查,下次给我50的权重

编辑:此例程将在1920x1080像素的地图上运行,因此需要数百万次;在重构过程中,性能可能是一个真正的问题。

对于循环来说呢

int weight = 0;
for (int dx = -1 ; dx <= 1 ; dx++) {
    for (int dy = -1 ; dy <= 1 ; dy++) {
        if (CheckWeight(new Point(4+dx, 4+dy))) {
            weight += (dx==0 && dy == 0) ? 100 : 10;
        }
     }
}
int x = 4;
int y = 4;
int weight = 0; 
for (int dx = -1; dx <= +1; dx++) {
    for (int dy = -1; dy <= +1; dy++) {
        if (CheckWeight(new Point(x+dx, y+dy)))
            weight += 10;
    }
}
intx=4;
int y=4;
整数权重=0;

for(int dx=-1;dx一种可能的方法是将公共代码重构为for循环,该循环将遍历目标点附近的所有点。示例代码如下:

var target = new Point(4, 4);

int weight = 0;
if (CheckWeight(target) == true)
    weight += 100;

var points = GetNearestPointsFrom(target);

foreach (var p in points)
{
    if (CheckWeight(p) == true)
        weight += 10;
}
您需要实现
getNearestPoints from
方法来返回正确的点。通过这种方式,您还将用于断言最近点的逻辑封装在一个单独的方法中,我发现这个方法更易于维护


更新: 考虑到您受到性能约束的限制,并且您提到可能需要通过另一个函数更改
检查权重
,我将验证是否将
if
检查包装到一个接受
谓词
的方法中,并且权重增量值不会对性能产生太大影响使用
CheckWeight
方法或仅执行一次增量。示例代码:

private static void GetWeight(Predicate<Point> predicate, int weightIncrement)
{
    int weight = 0;
    if (predicate(new Point(4, 4)) == true)
        weight += 100;
    if (predicate(new Point(4, 5)) == true)
        weight += weightIncrement;
    // ... Remaining checks ...
}
私有静态void GetWeight(谓词谓词,int-weightIncrement)
{
整数权重=0;
if(谓词(新点(4,4))==true)
重量+=100;
if(谓词(新点(4,5))==true)
重量+=重量增量;
//…剩下的支票。。。
}

第一个
+=100
是故意的还是仅仅是一个打字错误?第一个是故意的,我基本上是在寻找一个40的权重,如果第一个像素(实际像素)满足我的条件,那么我要检查的像素,或者超过一半的周围像素,需要满足我要检查的条件。“==true”部分是多余的。CheckWeight已经返回了一个
布尔值,这是if语句所需要的。if
CheckWeight
返回
true
您基本上得到了
true==true-->true
。如果不是,您得到的是
false==true-->false
。这就像将一个数字乘以1。它不会改变任何东西。true,是f吗更多地关注条件,我完全忽略了这一点!虽然这是可行的…但当我检查250万像素时,它的运行速度要慢得多(在它用这种方法检查它们大约2秒钟之前,需要71到73秒)@BrianDeragon我明白了!这一定是你最初编写这些循环代码的原因。@Brian Deragon,你对这个问题隐瞒了这个要求,这可能会使大多数不知道你有性能要求的答案无效。对不起,我自己也没有意识到这是个问题……直到我们检查了几个问题百万像素1000x1000,或1920x1080@BrianDeragon我更新了一些可能更有效的答案。它不会接近你的2.5秒,但可能也会比73秒快很多。通过回顾你的例子,我发现中心点有+100,而不是+10。但是你可以很容易地纠正它。你也可以使用一个3x3权重矩阵(或者我应该称之为过滤矩阵)。这将是一个更通用、更灵活的方法(我必须读取+100的检查,太慢了,请参见dasblins的回答,另外,代码变得有点凌乱,这是因为中心像素的权重不同。使用循环时,CheckWeight仅在一个位置调用。您可以直接在循环内了解CheckWeight的作用。如果性能有问题,也许您可以避免在任何时候创建点。)y循环,而不是调用CheckWeight(x,y)比Dasblin的答案更快()“但是平均在18到23秒之间,速度还是慢了很多。”Brian Deragon,检查我在另一个答案中的评论。没有人知道性能要求,所以大多数人只会根据他们所知道的来回答。很好,我喜欢使用谓词,这很有帮助;没有想到这一点,也没有真正地减慢速度,3到5秒。”每次运行秒数,稍微慢一点,但我可以应付,维护噩梦已经过去,很容易支付费用。
private static void GetWeight(Predicate<Point> predicate, int weightIncrement)
{
    int weight = 0;
    if (predicate(new Point(4, 4)) == true)
        weight += 100;
    if (predicate(new Point(4, 5)) == true)
        weight += weightIncrement;
    // ... Remaining checks ...
}