LINQ不等于不工作?

时间:2014-09-30 21:56:39

标签: c# linq powershell

我试图解决我需要管理数字范围数组的问题,我需要确保集合中没有数字范围相互冲突。对于那些已经弄明白的人:是的,我在谈论网络,但我正试图简化这篇文章。 : - )

我花了一分钟(或两个人),但我想出了以下逻辑测试:

  1. 确定现有的结尾(last)是否小于新的开头(new first)。
  2. 确定现有的开头(第一个)是否大于新的结尾(新的最后一个)。
  3. 如果#1的结果与#2的结果不同,则范围不会发生冲突。
  4. 尽我所知(并在Excel中复制),这是合理的逻辑。但是,当我尝试在C#中的LINQ中编写此逻辑并随后在PowerShell中执行时,它不起作用。我提前为长篇PowerShell输出道歉。

    我应该如何在LINQ中编写这个逻辑?我哪里出错了?

    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命令:

    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
    

1 个答案:

答案 0 :(得分:1)

谢谢你@JonSkeet,因为你发现第二个问题就是重写它的建议。

所以,我的问题的答案有两个:

  1. LINQ逻辑是声音(使用!=),但InsertItem中的逻辑被颠倒了。我要么需要更改!= = ==或将if (existingItem.Any())更改为if (!existingItem.Any())。我选择了前者。
  2. $ range4不存在(从其他测试中剩余)。 叹息
  3. 这是完成的工作代码(全部在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;
        }
    }