C#:端点为空(无穷大)时的范围交集

时间:2009-11-13 14:01:02

标签: c# null range intersection icomparable

好的,我有这些交集方法来处理范围,只要范围端点不为空,它们就可以正常工作:

public static bool Intersects<T>(this Range<T> first, Range<T> second, IComparer<T> comparer)
{
    return comparer.Compare(first.Start, second.End) <= 0 
        && comparer.Compare(first.End, second.Start) >= 0;
}

public static Range<T> GetIntersectionWith<T>(this Range<T> first, Range<T> second,
    IComparer<T> comparer)
{
    // Return null, if any range is null or if they don't  intersect at all
    if (first == null || second == null || !Intersects(first, second, comparer))
        return null;

    var start = comparer.Compare(first.Start, second.Start) < 0 
                    ? second.Start 
                    : first.Start;
    var end = comparer.Compare(first.End, second.End) > 0 
                    ? second.End 
                    : first.End;

    return Range.Create(start, end);
}

我现在的问题是我希望他们完全支持null端点。空终点意味着该范围在该方向上变为无穷大。我希望传递的两个测试,例如:{/ p>

[Test]
public void Intersects_Intersecting_OneEndsWithNull()
{
    var a = Range.Create("a", "k");
    var b = Range.Create("c", null);

    Assert.That(a.Intersects(b), Is.True);
    Assert.That(b.Intersects(a), Is.True);
}

[Test]
public void GetIntersectionWith_Intersecting_OneStartingAndOneEndingWithNull()
{
    var a = Range.Create(null, "k");
    var b = Range.Create("f", null);
    var expected = Range.Create("f", "k");

    Assert.That(a.GetIntersectionWith(b), Is.EqualTo(expected));
    Assert.That(b.GetIntersectionWith(a), Is.EqualTo(expected));
}

它不能立即起作用的原因是null被认为少于一切。但是这里null有时被认为是更大而不是一切。

知道如何以一种好的方式解决这个问题吗?

我想我要先检查null并做一些特别的事情或做一些IComparer<T>包装......但我无法弄清楚哪个或如何他们必须工作。必须记住它也可以给出任何类型的比较器,所以从技术上来说,范围可能是相反的方向,只要给定的比较器当然考虑到这一点(在实际代码中,如果开始时我会抛出异常)根据给定的比较器结束后)。无论如何,我有点迷失在这里:P

1 个答案:

答案 0 :(得分:1)

我认为您需要考虑比较中的空值。

这会有所帮助吗?

public static bool Intersects<T>(this Range<T> first, Range<T> second, IComparer<T> comparer)
        {    
            return (ReferenceEquals(first.Start, null) || ReferenceEquals(second.End, null) || comparer.Compare(first.Start, second.End) <= 0)
                && (ReferenceEquals(first.End, null) || ReferenceEquals(second.Start, null) || comparer.Compare(first.End, second.Start) >= 0);
        }

好的,第二部分。将start和end设置为null,并且仅当两者都不为null时才设置为start / end值。

public static Range<T> GetIntersectionWith<T>(this Range<T> first, Range<T> second, IComparer<T> comparer)
    {
        // Return null, if any range is null or if they don't  intersect at all
        if (first == null || second == null || !Intersects(first, second, comparer))
            return null;

        T start;
        if (ReferenceEquals(first.Start, null))
            start = second.Start;
        else if (ReferenceEquals(second.Start, null))
            start = first.Start;
        else
            start = comparer.Compare(first.Start, second.Start) < 0 
                        ? second.Start 
                        : first.Start;        
        T end;
        if (ReferenceEquals(first.End, null))
            end = second.End;
        else if (ReferenceEquals(second.End, null))
            end = first.End;
        else
            end = comparer.Compare(first.End, second.End) > 0 
                        ? second.End 
                        : first.End;

        return Range.Create(start, end);
    }