将自定义类的属性与变量进行比较时抛出异常

时间:2016-10-06 18:48:40

标签: vb.net linq comparison

我有以下课程:

Public Class Row

    Public Sub New()
    End Sub

    Public Sub New(ByRef lookupTable As LookupTable)
        myLookupTable = lookupTable
    End Sub

    Private myLookupTable As LookupTable

    <XmlAttribute("value")> _
    Public Property Value As Double

    <XmlArray("values")> _
    <XmlArrayItem("value")> _
    Public Property Values As List(Of Double)

    <XmlIgnore> _
    Public ReadOnly Property LookupTable As LookupTable
        Get
            Return myLookupTable
        End Get
    End Property
End Class

我正在努力做到以下几点:

Dim yIndexBelow As Integer = Rows.IndexOf(Rows.Where(Function(row) row.Value <= yVal).Max())
Dim yIndexAbove As Integer = Rows.IndexOf(Rows.Where(Function(row) row.Value >= yVal).Min())
Dim yProportion As Double = (yVal - Rows(yIndexBelow).Value) / (Rows(yIndexAbove).Value - Rows(yIndexBelow).Value)

第二行 上,会抛出异常:At least one object must implement IComparable.呃......什么?

从何时Double未实现IComparable?很明显它确实如此。

更重要的是;为什么它只在第二个行失败?

任何想法?。

P.S。  如果您想知道,yVal 已设置

2 个答案:

答案 0 :(得分:2)

为了证明你的观点,这个课程就足够了

ggplot(df, aes(x = x)) + 
    geom_histogram(binwidth = .05, position = "dodge", color = "black", fill = "transparent") + 
    geom_vline(aes(xintercept = mean), linetype = "dashed", color = "red") +
    theme_bw() +
    scale_x_continuous(name="Values", expand = c(0, 0),
                       breaks = sort(c(seq(0,10,1), mean)), 
                       labels = sort(c(0L:10L, round(mean, digits = 2))))

正如您所提到的,解决方案是实现IComparable。见https://support.microsoft.com/en-us/kb/320727

Public Class Row
    Public Property Value As Double
End Class

测试用例仅需要索引查找部分。这是一个很好的例子。这应该使用上面Public Class Row Implements IComparable(Of Row) Public Property Value As Double Public Function CompareTo(other As Row) As Integer _ Implements IComparable(Of Row).CompareTo Return If(Me.Value > other.Value, 1, -1) End Function End Class 的两个版本进行测试。可以看出,当Row没有实现IComparable时,第一部分可以工作,因为只有一个元素,正如你所指出的那样,但第二部分没有。简单地说,LINQ的Max函数只是短路比较,因为只有一个元素。

Row

Sub Main() Dim yVal As Double = 6.7 Dim yIndexBelow As Integer Dim yIndexAbove As Integer Dim rows As New List(Of Row)() rows.Add(New Row() With {.Value = 5}) yIndexBelow = rows.IndexOf(rows.Where(Function(row) row.Value <= yVal).Max()) yIndexAbove = rows.IndexOf(rows.Where(Function(row) row.Value >= yVal).Min()) Console.WriteLine("Rows: {0}", String.Join(", ", rows.Select(Of Double)(Function(r) r.Value))) Console.WriteLine("Index below {0}: {1}", yIndexBelow, If(yIndexBelow = -1, "N/A", rows(yIndexBelow).Value)) Console.WriteLine("Index above {0}: {1}", yIndexAbove, If(yIndexAbove = -1, "N/A", rows(yIndexAbove).Value)) rows.Add(New Row() With {.Value = 6}) rows.Add(New Row() With {.Value = 2}) rows.Add(New Row() With {.Value = 10}) rows.Add(New Row() With {.Value = -6}) rows.Add(New Row() With {.Value = 12}) rows.Add(New Row() With {.Value = 1}) yIndexBelow = rows.IndexOf(rows.Where(Function(row) row.Value <= yVal).Max()) yIndexAbove = rows.IndexOf(rows.Where(Function(row) row.Value >= yVal).Min()) Console.WriteLine("Rows: {0}", String.Join(", ", rows.Select(Of Double)(Function(r) r.Value))) Console.WriteLine("Index below {0}: {1}", yIndexBelow, If(yIndexBelow = -1, "N/A", rows(yIndexBelow).Value)) Console.WriteLine("Index above {0}: {1}", yIndexAbove, If(yIndexAbove = -1, "N/A", rows(yIndexAbove).Value)) End Sub 实现IComparable时的输出:

  

yVal:6.7   
行:5   
指数低于0:5   
指数高于-1:N / A.   
行:5,6,2,10,6,12,1   
指数低于1:6   
指数高于3:10

这很有趣,我检查了Google / SO / MSDN是否有任何关于此行为的提及,但找不到任何内容。从逻辑上讲,它是有道理的,但可能导致混淆点。

答案 1 :(得分:0)

答案是因为Min()Max()正在尝试比较未实现Row的{​​{1}}。第一行工作的原因是因为IComparable只有一行可以返回(在我的测试用例中)。

所以这个故事的寓意是:比较可比的东西(呃!) Max()Max()如果只有一个对象,就不会抱怨可比性在集合中。