我试图解决我需要管理数字范围数组的问题,我需要确保集合中没有数字范围相互冲突。对于那些已经弄明白的人:是的,我在谈论网络,但我正试图简化这篇文章。 : - )
我花了一分钟(或两个人),但我想出了以下逻辑测试:
尽我所知(并在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
答案 0 :(得分:1)
谢谢你@JonSkeet,因为你发现第二个问题就是重写它的建议。
所以,我的问题的答案有两个:
InsertItem
中的逻辑被颠倒了。我要么需要更改!= = ==或将if (existingItem.Any())
更改为if (!existingItem.Any())
。我选择了前者。这是完成的工作代码(全部在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;
}
}