#c# #mono #unity3d #compareto #icomparable
#c# #mono #unity-игровой движок #сравнение #icomparable
Вопрос:
Этот код успешно выполняется в .NET 4.0
public void CompareTest()
{
var m1 = new Foo { Order = 1 };
var m2 = new Foo { Order = 2 };
var c1 = new Bar { Order = -1 };
var c2 = new Bar { Order = 3 };
var list1 = new List<IOrderable> { m1, m2, c1, c2 };
var list2 = new List<Bar> { c1, c2 };
list1.Sort();
list2.Sort();
}
public interface IOrderable : IComparable<IOrderable>
{
int Order { get; set; }
}
public class Foo : IOrderable
{
public int Order { get; set; }
public int CompareTo(IOrderable other)
{
return Order.CompareTo(other.Order);
}
}
public class Bar : IOrderable
{
public int Order { get; set; }
public int CompareTo(IOrderable other)
{
return Order.CompareTo(other.Order);
}
}
Однако в Mono 2.6 (в Unity3D) она выдает исключение:
ArgumentException: does not implement right interface
Это приводит ко второму виду ( list2.Sort()
), но не к первому
Я вроде как новичок во всех этих сравнениях, поэтому извините, если я упускаю здесь что-то очевидное.
Почему он жалуется на то, что не реализует правильный интерфейс? Она реализована. Есть идеи, что здесь происходит? почему это работает в .NET, но не в Mono?
Спасибо.
РЕДАКТИРОВАТЬ: полный стек
ArgumentException: does not implement right interface
System.Collections.Generic.Comparer`1 DefaultComparer[ShowEmAll.BetterBehaviourEditor Bar].Compare (ShowEmAll.Bar x, ShowEmAll.Bar y) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections.Generic/Comparer.cs:86)
System.Array.compare[Bar] (ShowEmAll.Bar value1, ShowEmAll.Bar value2, IComparer`1 comparer) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Array.cs:1744)
System.Array.qsort[Bar,Bar] (.Bar[] keys, .Bar[] items, Int32 low0, Int32 high0, IComparer`1 comparer) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Array.cs:1721)
System.Array.Sort[Bar,Bar] (.Bar[] keys, .Bar[] items, Int32 index, Int32 length, IComparer`1 comparer) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Array.cs:1674)
Rethrow as InvalidOperationException: The comparer threw an exception.
System.Array.Sort[Bar,Bar] (.Bar[] keys, .Bar[] items, Int32 index, Int32 length, IComparer`1 comparer) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Array.cs:1677)
System.Array.Sort[Bar] (.Bar[] array, Int32 index, Int32 length, IComparer`1 comparer) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Array.cs:1623)
System.Collections.Generic.List`1[ShowEmAll.BetterBehaviourEditor Bar].Sort () (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections.Generic/List.cs:568)
ShowEmAll.BetterBehaviourEditor.CompareTest () (at Assets/Vexe/ShowEmAll/Core/Editor/CustomEditors/BetterBehaviourEditor.cs:81)
ShowEmAll.BetterBehaviourEditor.OnEnable () (at Assets/Vexe/ShowEmAll/Core/Editor/CustomEditors/BetterBehaviourEditor.cs:62)
Комментарии:
1. Пожалуйста, покажите полную трассировку стека исключений. Мы понятия не имеем, на что жалуются, когда на данный момент.
2. Итак, какая строка равна 81?
list1.Sort()
илиlist2.Sort()
?3. Я добавил это тоже к своему вопросу, но не к редактированию. Проблема второго рода возникает из-за переполнения стека.
list2.Sort()
4. Похоже, что это, вероятно, ошибка Mono, но у меня это работает в Mono 3.3
5. Спасибо Unity за то, что оставили нас с ржавым Mono = (
Ответ №1:
Во-первых, похоже, что это, вероятно, ошибка Mono в Comparer<T>.Default
, которую следует заметить, если T
реализовать IComparable<Foo>
для некоторых Foo
, которые являются либо реализациями интерфейса T
, либо базовым типом T
.
Для обходных путей предлагается четыре варианта:
- Реализуйте не универсальный
IComparable
интерфейс вBar
, возможно, просто делегируя реализациюCompareTo(IOrder)
- Реализуйте
IComparable<Bar>
вBar
, вероятно, просто делегируя реализациюCompareTo(IOrder)
- Всегда используйте
List<IOrder>
, даже если каждый элемент в нем являетсяBar
- Укажите
Comparer<T>
toList<T>.Sort
— я подозреваю, что вы можете довольно легко создать свою собственную реализацию с использованием дженериков.
Комментарии:
1. Спасибо! всегда рядом со мной: D