简体   繁体   English

LINQ不等于不起作用?

[英]LINQ Not Equals Not Working?

I'm trying to solve a problem where I need to manage an array of number ranges and I need to ensure that no number ranges in the collection collide with each other. 我正在尝试解决一个问题,我需要管理一个数字范围的数组,并且需要确保集合中的数字范围不会相互冲突。 For those of who who already figured it out: yes, I'm talking about networks, but I'm trying to simplify for this post. 对于那些已经弄清楚了的人:是的,我在谈论网络,但是我正在尝试简化本文。 :-) :-)

It took me a minute (or maybe two), but I came up with the following logic test: 我花了一分钟(或者可能是两分钟),但是我想出了以下逻辑测试:

  1. Determine if the existing ending (last) is less than the new beginning (new first). 确定现有的结尾(最后一个)是否小于新的开头(新的第一个)。
  2. Determine if the existing beginning (first) is greater than the new ending (new last). 确定现有的开头(第一个)是否大于新的结尾(新的最后一个)。
  3. If the result of #1 is not the same as the result of #2, then the ranges do not collide. 如果#1的结果与#2的结果不同,则范围不会冲突。

As best as I can tell (and replicate in Excel), this is sound logic. 据我所知(并在Excel中复制),这是合理的逻辑。 However, when I try to write this logic in LINQ in C# and subsequently execute in PowerShell, it doesn't work. 但是,当我尝试用C#在LINQ中编写此逻辑并随后在PowerShell中执行时,它不起作用。 I apologize for the lengthy PowerShell output in advance. 对于冗长的PowerShell输出,我深表歉意。

How should I be writing this logic in LINQ? 我应该如何在LINQ中编写此逻辑? Where did I go wrong? 我哪里做错了?

C# Code: C#代码:

public class NumberRange
{
    public int First;
    public int Last;

    public NumberRange()
    {
    }

    public NumberRange(int first, int last)
    {
        First = first;
        Last = last;
    }
}

public class NumberRangeCollection : Collection<NumberRange>
{
    protected override void InsertItem(int index, NumberRange item)
    {
        NumberRange[] existingItem = this.Where(x => ((x.Last < item.First) != (x.First > item.Last))).ToArray();
        if (existingItem.Any()) throw new ArgumentException("New range collides with an existing range.", "item");

        base.InsertItem(index, item);
    }
}

PowerShell commands: PowerShell命令:

PS> $range1 = New-Object TestLibrary.NumberRange -ArgumentList @(3, 4)
PS> $range2 = New-Object TestLibrary.NumberRange -ArgumentList @(4, 5)
PS> $range3 = New-Object TestLibrary.NumberRange -ArgumentList @(5, 6)
PS> $bigrange = New-Object TestLibrary.NumberRange -ArgumentList @(3, 6)
PS> $b = New-Object TestLibrary.NumberRangeCollection
PS> $b.Add($range1)
PS> $b.Add($bigrange) # This should fail, but doesn't
PS> $b | Format-Table -AutoSize

First Last
----- ----
    3    4
    3    6


PS> $b = New-Object TestLibrary.NumberRangeCollection
PS> $b.Add($range2)
PS> $b.Add($bigrange) # This should fail, but doesn't
PS> $b | Format-Table -AutoSize

First Last
----- ----
    4    5
    3    6


PS> $b = New-Object TestLibrary.NumberRangeCollection
PS> $b.Add($range3)
PS> $b.Add($bigrange) # This should fail, but doesn't
PS> $b | Format-Table -AutoSize

First Last
----- ----
    5    6
    3    6


PS> $b = New-Object TestLibrary.NumberRangeCollection
PS> $b.Add($range4)
PS> $b.Add($bigrange) # This should fail, does, but doesn't throw the right exception.
Exception calling "Add" with "1" argument(s): "Object reference not set to an instance of an object."
At line:1 char:1
+ $b.Add($bigrange)
+ ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : NullReferenceException

PS> $b | Format-Table -AutoSize
PS> $b = New-Object TestLibrary.NumberRangeCollection
PS> $b.Add($bigrange)
PS> $b.Add($range1) # This should fail, but doesn't
PS> $b.Add($range2) # This should fail, but doesn't
PS> $b.Add($range3) # WOOT!  The only one that works!
Exception calling "Add" with "1" argument(s): "New range collides with an existing range.
Parameter name: item"
At line:1 char:1
+ $b.Add($range3)
+ ~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentException

PS> $b.Add($range4) # This should fail, does, but doesn't throw the right exception.
Exception calling "Add" with "1" argument(s): "Object reference not set to an instance of an object."
At line:1 char:1
+ $b.Add($range4)
+ ~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : NullReferenceException

PS> $b | Format-Table -AutoSize

First Last
----- ----
    3    6
    3    4
    4    5

Thank you, @JonSkeet, for your suggestion of rewriting it as I found the second problem doing that. 谢谢@JonSkeet,因为我发现这样做的第二个问题,因此建议您重写它。

So, the answer to my question is two fold: 因此,我的问题的答案有两个:

  1. The LINQ logic was sound (using !=), but the logic in InsertItem was reversed. LINQ逻辑很好(使用!=),但是InsertItem中的逻辑相反。 I either needed to change != to == or change if (existingItem.Any()) to if (!existingItem.Any()) . 我要么需要将!=更改为==,要么将if (existingItem.Any())更改为if (!existingItem.Any()) I chose the former. 我选择了前者。
  2. $range4 didn't exist (leftover from other testing). $ range4不存在(其他测试的剩余部分)。 sigh

Here is the completed working code (all in C#): 这是完整的工作代码(全部在C#中):

public class NumberRange
{
    public int First;
    public int Last;

    public NumberRange()
    {
    }

    public NumberRange(int first, int last)
    {
        First = first;
        Last = last;
    }
}

public class NumberRangeCollection : Collection<NumberRange>
{
    public NumberRange BigRange = new NumberRange(3, 6);
    public NumberRange Range1 = new NumberRange(3, 4);
    public NumberRange Range2 = new NumberRange(4, 5);
    public NumberRange Range3 = new NumberRange(5, 6);

    protected override void InsertItem(int index, NumberRange item)
    {
        NumberRange[] existingItem = this.Where(x => ((x.Last < item.First) == (x.First > item.Last))).ToArray();
        if (existingItem.Any()) throw new ArgumentException("New range collides with an existing range.", "item");

        base.InsertItem(index, item);
    }

    public NumberRangeCollection RunTest1()
    {
        Clear();
        Add(Range1);
        Add(BigRange);
        return this;
    }

    public NumberRangeCollection RunTest2()
    {
        Clear();
        Add(Range2);
        Add(BigRange);
        return this;
    }

    public NumberRangeCollection RunTest3()
    {
        Clear();
        Add(Range3);
        Add(BigRange);
        return this;
    }

    public NumberRangeCollection RunTest4()
    {
        Clear();
        Add(BigRange);
        try
        {
            Add(Range1);
        }
        catch
        {
        }
        try
        {
            Add(Range2);
        }
        catch
        {
        }
        try
        {
            Add(Range3);
        }
        catch
        {
        }
        return this;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM