【问题标题】:C# List<T>.Find(x=>x.Rectangle.Contains(Point)) FAILC# List<T>.Find(x=>x.Rectangle.Contains(Point)) 失败
【发布时间】:2010-02-04 05:28:44
【问题描述】:

对于我的一生,我无法理解为什么这段代码会产生以下输出......

如果类型公开了 Rectangle 属性并且您使用了矩形对象的 Contains 方法,我认为在使用 List 和 lambda 时存在错误或其他问题......并且当 List Find 方法失​​败时显式迭代证明是正确的...... .

单程

代码

public GridSquare WorldToKeyPadSub(Point location)
    {
        location = _Map.WorldToClient(location);
        GridSquare gs = this.Find(x => x.Rectangle.Contains(location));
        GridSquare kp = gs.Find(x => x.Rectangle.Contains(location));
        List<GridSquare> list = kp.FindAll(x=>x.Rectangle.Contains(location));
        u.dp(list.Count);
        GridSquare sub = kp.Find(x => x.Rectangle.Contains(location));

        if (sub == null)
        {
            u.dp("Location to look for " + location);
            u.dp("Found Location in grid square " + gs.ToString());
            u.dp("grid square bounds " + gs.Rectangle.ToString());
            u.dp("Found Location in Keypad " + kp.ToString());
            u.dp("key pad bounds " + kp.Rectangle.ToString());
            u.dp("Sub Key Pads Print All sub keys in this grid.keypad");
            foreach (GridSquare t in kp)
            {
                u.dp(t.ToString() + "  " + t.Rectangle.ToString());                   

            }
            u.dp("Sub Key Pads Print Explicit Finds");
            foreach (GridSquare t in kp)
            {
                if (location.X >= t.Location.X
                    && location.Y >= t.Location.Y
                    && location.X <= t.Location.X + t.Rectangle.Width
                    && location.Y <= t.Location.Y + t.Rectangle.Height)
                {
                    u.dp(true);
                    u.dp(t.ToString() + "  " + t.Rectangle.ToString());
                }

            }
        }
        return sub;
    }

这会产生以下输出...

注意显式矩形(又名手动方法)如何找到包含该位置的网格正方形......内部 GDI 版本失败......

Location to look for {X=1476,Y=1716}
Found Location in grid square GS: 14.3.0.0
grid square bounds {X=1398,Y=1650,Width=100,Height=100}
Found Location in Keypad GS: 14.3.6.0
key pad bounds {X=1465,Y=1683,Width=33,Height=34}
Sub Key Pads Print All sub keys in this grid.keypad
GS: 14.3.6.7  {X=1465,Y=1683,Width=11,Height=11}
GS: 14.3.6.8  {X=1476,Y=1683,Width=11,Height=11}
GS: 14.3.6.9  {X=1487,Y=1683,Width=11,Height=11}
GS: 14.3.6.4  {X=1465,Y=1694,Width=11,Height=11}
GS: 14.3.6.5  {X=1476,Y=1694,Width=11,Height=11}
GS: 14.3.6.6  {X=1487,Y=1694,Width=11,Height=11}
GS: 14.3.6.1  {X=1465,Y=1705,Width=11,Height=11}
GS: 14.3.6.2  {X=1476,Y=1705,Width=11,Height=11}
GS: 14.3.6.3  {X=1487,Y=1705,Width=11,Height=11}
Sub Key Pads Print Explicit Finds
True
GS: 14.3.6.1  {X=1465,Y=1705,Width=11,Height=11}
True
GS: 14.3.6.2  {X=1476,Y=1705,Width=11,Height=11}
A first chance exception of type 'System.NullReferenceException'

【问题讨论】:

    标签: .net contains point


    【解决方案1】:

    Rectangle.Contains(Point) 在矩形的上限上是排他的(严格小于)。

    例如,Rectangle.Contains(Point) 在您的上下文中执行的等效检查是:

    foreach (GridSquare t in kp) 
    { 
        if (location.X >= t.Location.X 
            && location.Y >= t.Location.Y 
            && location.X < t.Location.X + t.Rectangle.Width   // < instead of <=
            && location.Y < t.Location.Y + t.Rectangle.Height) // < instead of <=
        { 
            u.dp(true); 
            u.dp(t.ToString() + "  " + t.Rectangle.ToString()); 
        } 
    
    } 
    

    如您所见,它将上限验证为严格小于,而不是小于或等于,您的方法与 Rectangle.Contains(Point) 之间的区别就在那里。

    在您的示例中传递的位置是 {X=1476,Y=1716},当传递给这些矩形的包含时:

    GS: 14.3.6.1  {X=1465,Y=1705,Width=11,Height=11}  
    GS: 14.3.6.2  {X=1476,Y=1705,Width=11,Height=11}  
    

    将返回 false,当你的返回 true 时。

    这就是为什么 kp.Find(x =&gt; x.Rectangle.Contains(location)); 返回 null,但您的手动检查返回 true。

    【讨论】:

    • 我想指出这是非法的...我建议使用 Mono 源作为参考。
    • 我想你的观点是可能的,但是我怀疑链接到 Mono 的 Cairo 对不使用它的人有什么好处。
    【解决方案2】:

    这是我发现的……

    考虑一下定义为 0,0,100,100...的矩形...

    人们会假设点 100,100 在该矩形内,但事实并非如此......

    Rectangle.Contains 不包括边界...换句话说,它只会对定义为 0,0,100,100 的矩形中 0,0 到 99,99 的所有点返回 true...

    我遇到的问题是,当您使用 GDI 绘制该矩形时……像素被向下和向右倾斜……

    最终效果是 Rectangle.Contains 包含矩形的顶部和左腿,不包括矩形的底部和右腿......从图形的角度来看......你可以放大到鼠标点击测试期间的像素级别...

    光标可能看起来就在矩形的上下边界之内...但由于 Rectangle.Contains 的右腿和下腿的专有性质,命中测试返回 false...

    SW

    【讨论】:

      【解决方案3】:

      我看到两件事你可以检查:

      1. 您的明确检查是包容性的 - 小于等于,大于等于。如果 Rectangle.Contains 是独占的,那么您的显式检查发现的两个点都将被忽略。

      2. 您确定 x.Location.X 和 .Y 始终与 x.Rectangle.X 和 .Y 相同吗?

      【讨论】:

        猜你喜欢
        • 2023-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多