Почему я получаю исключение нулевой ссылки при сортировке IComparer?

У меня есть список настраиваемых типов объектов, скажем

Dim a As New List(Of CustomType)

заполняется экземплярами. У меня есть класс сравнения, который наследует

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

который называется с помощью

a.Sort(New CustomTypeComparer)

метод. Единственный метод компаратора Compare() вызывается автоматически, однако иногда метод дает сбой, потому что x не определено или «не установлено в экземпляр объекта».

Я просмотрел отсортированный список, чтобы проверить, что ни один из элементов не является Ничто, подтверждено просмотром a.Contains(Nothing), который возвращает False, и проверен с использованием других компараторов, которые смотрят на другие части объекта, ни у одного из них нет проблем со списком, только это один.

Как я могу изучить проблему глубже? Есть ли какие-нибудь идеи, которые люди могут дать по этому вопросу?

Обновление:

Читая справочный исходный код платформы, метод сортировки списка использует базовый метод Array.Sort(). Взяв подсказку, я попытался использовать метод List.TrimExcess() в списке, это изменило поведение, и IComparer не передаёт Nothing. Комментатор обнаружил, что IComparers должны сравнивать пустые значения, что в сочетании с базовой границей массива больше, чем у массива, и молча содержит Nothings в нем для создания ожидаемой функциональности.


person J Collins    schedule 06.06.2018    source источник
comment
В этом случае, вероятно, будет полезен минимальный воспроизводимый пример.   -  person Steven Doggart    schedule 06.06.2018
comment
Спасибо, Стивен, я надеюсь получить больше понимания того, что может вызвать проблему, чем просто решение. то есть при каких обстоятельствах компаратор может получить «Ничто», когда список не содержит ничего. Я думаю о неудачном приведении в коде фреймворка, хотя все элементы списка имеют один и тот же тип.   -  person J Collins    schedule 06.06.2018
comment
Ага. Я понимаю. Вот почему я сказал, вероятно, и не голосовал за закрытие. Судя по вашему вопросу, я предполагаю, что вы довольно тщательно провели тестирование, поэтому я склонен вам верить. Но если бы вы предоставили MCVE, все сомнения в этом отношении были бы устранены. Кроме того, в содержании списка может быть подсказка, которая поможет объяснить, почему это происходит.   -  person Steven Doggart    schedule 06.06.2018
comment
Я отчетливо опасаюсь, что могу потратить весь день, пытаясь создать изолированный тестовый пример, который никогда не даст сбой, потому что в принципе этого не должно быть. Проблема определенно будет заключаться в тонкости более крупной реализации, которая потребует отправки большого количества конфиденциальных данных.   -  person J Collins    schedule 06.06.2018
comment
Что ж, если вам не так важен ответ, просто проверьте наличие Nothing в компараторе (поскольку вы все равно должны это делать) и не беспокойтесь об этом :)   -  person Steven Doggart    schedule 06.06.2018
comment
Если вы действительно хотите знать, как работает сортировка List(Of T), вы можете сами прочитать код. Код для реализации класса .NET Core, Mono и .NET Framework доступен в Интернете. Очевидно, что нет никакой гарантии, что все они реализованы одинаково, поэтому вашему компаратору было бы лучше предположить, что ему может быть передано значение null.   -  person Steven Doggart    schedule 06.06.2018
comment
Вы проверяли свой список, когда он разбился или незадолго до этого?   -  person the_lotus    schedule 06.06.2018
comment
@the_lotus отладчик останавливает выполнение, и когда я поднимаюсь по стеку и смотрю на список, я вижу, что в нем есть. К вашему сведению, в настоящее время это однопоточное приложение, ничего не мигает ..!   -  person J Collins    schedule 06.06.2018
comment
@StevenDoggart Было бы очень легко добавить тест, но это не ожидаемое поведение, и простое замалчивание таких вещей вызывает у меня желание.   -  person J Collins    schedule 06.06.2018
comment
Возможно, но согласно официальной документации, реализации компаратора должны принимать null: Сравнение null с любым ссылочным типом разрешено и не генерирует исключения. Нулевая ссылка считается меньшей, чем любая ненулевая ссылка. Таким образом, учитывая такое определение интерфейса, нет никаких причин, по которым те, кто реализовал алгоритм сортировки, будут изо всех сил стараться избежать этого.   -  person Steven Doggart    schedule 06.06.2018
comment
@StevenDoggart Думаю, я очень близок к ответу. Списки основаны на огромных массивах, заполненных пустыми элементами. Сортировка списка сортирует базовый массив, в котором есть Nothings, что приводит к ошибке.   -  person J Collins    schedule 06.06.2018
comment
Это имеет смысл, да.   -  person Steven Doggart    schedule 06.06.2018


Ответы (1)


Если вы просто ищете справку по отладке, запустите CustomTypeComparer следующим образом.

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
person dbasnett    schedule 06.06.2018