1

I have a list of custom object types say

Dim a As New List(Of CustomType)

populated with instances. I have a comparer class that inherits

Public Class CustomTypeComparer
    Implements IComparer(Of CustomType)
    Public Function Compare(x As CustomType, y As CustomType) As Integer Implements IComparer(Of CustomType).Compare
        ...
    End Function
End Class

that is called using the

a.Sort(New CustomTypeComparer)

method. The comparer's only method Compare() is called automatically, however occasionally the method fails because x is undefined or 'Not set to an instance of an object'.

I have scoured the list being sorted to check none of the elements are Nothing, confirmed with a watch on a.Contains(Nothing) which returns False and checked using other comparers that look at other parts of the object, none of those have problems with the list, only this one.

How can I study the problem any deeper? Is there any insight people can give on this issue?

Update:

Reading the reference source code of the framework, the list sort method uses the underlying Array.Sort() method. Taking a hint from that and I tried using the List.TrimExcess() method on the list, this has changed the behaviour and no Nothings are passed to the IComparer. A commenter discovered that IComparers are expected to compare nulls, which combines with the Array's underlying bound being greater than the array and silently having Nothings in it to generate expected functionality.

J Collins
  • 2,106
  • 1
  • 23
  • 30
  • A [mcve] would probably be helpful in this case. – Steven Doggart Jun 06 '18 at 14:54
  • Thanks Steven, I'm hoping to get more of an understanding in what could cause the problem than simply a solution. i.e. under what circumstances could the comparer be fed a 'Nothing', when the list does not contain any. I am thinking along the lines of a failed cast in the framework code, though all list items are of exactly the same type. – J Collins Jun 06 '18 at 14:58
  • Yup. I understand. That's why I said "probably" and didn't vote to close. I'm guessing by your question that you have been pretty thorough in your testing, so I tend to believe you. But if you provided a MCVE, all doubt in that regard would be removed. Also, there may be a clue in the contents of the list that would help explain why it happens. – Steven Doggart Jun 06 '18 at 15:01
  • My distinct fear is I could spend my afternoon trying to make an isolated test case that never fails, because in principle it shouldn't. The problem is definitely going to be a subtlety in the bigger implementation which would require shipping out a bunch of sensitive data. – J Collins Jun 06 '18 at 15:10
  • 1
    Well, if you don't care that much about an answer, then just check for `Nothing` in your comparer (since you should be doing that anyway) and don't worry about it :) – Steven Doggart Jun 06 '18 at 15:11
  • If you really want to know how the `List(Of T)` sort works, you can read the code yourself. The code for the .NET Core, Mono, and .NET Framework implementations for the class are all available online. There's no guarantee, obviously, that they are all implemented the same way, which would be why it'd be best for your comparer to assume that null could be passed to it. – Steven Doggart Jun 06 '18 at 15:12
  • Have you check your list when it crashed or just before? – the_lotus Jun 06 '18 at 16:36
  • @the_lotus the debugger stops execution and when I go up the stack and look at the list I can see what is in it. FYI it is a single threaded application at present, nothing flash..! – J Collins Jun 06 '18 at 17:20
  • @StevenDoggart It'd be super easy to add the test, but it's not expected behaviour and just glossing over things like that gives me the willys. – J Collins Jun 06 '18 at 17:24
  • 2
    That may be, but according to the [official documentation](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.icomparer-1.compare), implementations of comparer must accept null: "_Comparing null with any reference type is allowed and does not generate an exception. A null reference is considered to be less than any reference that is not null._" So, given that definition of the interface, there's no reason why those who implemented the sort algorithm would go out of their way to avoid that happening. – Steven Doggart Jun 06 '18 at 17:45
  • @StevenDoggart I think I'm pretty close to the answer. Lists are based on oversized arrays full of nothings. The List sort sorts the underlying array that has Nothings in it, leading to the error. – J Collins Jun 06 '18 at 18:00
  • That makes sense, yes. – Steven Doggart Jun 06 '18 at 18:03

1 Answers1

0

If you are just looking for debug help start CustomTypeComparer off like this

Public Class CustomTypeComparer
    Implements IComparer(Of CustomType)
    Public Function Compare(x As CustomType, y As CustomType) As Integer Implements IComparer(Of CustomType).Compare
        If x Is Nothing Then
            Stop
        ElseIf y Is Nothing Then
            Stop
dbasnett
  • 11,334
  • 2
  • 25
  • 33