Сначала давайте посмотрим на определение оператора ===
. Это не просто проверка равенства между значениями двух экземпляров, но проверка того, указывают ли две переменные на точно такой же экземпляр объекта ( см. «Операторы идентификации» здесь ).
Итак, ваш пример кода не совсем верен:
var a1 = A()
var a2 = A()
var a3 = a2
a1 === a2 // actually false, a1 and a2 were instantiated separately
a2 === a3 // true, because they are the same instance
Таким образом можно сравнивать только классы, потому что все, что не является классом в Swift, имеет типизированный тип * и два значения. переменные могут не указывать на один и тот же экземпляр.
Поэтому, если вы попытаетесь сравнить обычный протокол с ===
, у Swift недостаточно информации для использования оператора. Экземпляры, которые вы сравниваете (p1
и p2
), могут быть экземплярами класса, или они могут быть экземплярами структуры, и во время компиляции Swift не может определить, все ли в порядке.
Если вы хотите иметь возможность использовать протокол в качестве типа таким образом и сравнивать с ===
, вам нужно объявить протокол только для класса следующим образом: используя class
в качестве первого элемента в списке наследования вашего протокола, например:
protocol P : class {
}
class A : P {
}
Теперь вы можете делать то, что пытались, без ошибки компилятора:
var p1:P = a1
var p2:P = a2
var p3:P = a3
p1 === p2 // false
p2 === p3 // true
* Семантически, в любом случае. Swift выполняет много закулисной типизации ссылок, но применяет это типизированное поведение со значениями, поэтому для целей этого обсуждения просто перейдите к struct
и enum
по-настоящему типизированным значениям.
Ваш компаратор мне кажется неправильным. Вы все еще просто выполняете сортировку в порядке текста по умолчанию. Конечно, вы хотите проанализировать два числа и отсортировать их на основе этого:
public int Compare(Object stringA, Object stringB)
{
string[] valueA = stringA.ToString().Split('/');
string[] valueB = stringB.ToString().Split('/');
if (valueA.Length != 2 || valueB.Length != 2)
{
stringA.ToString().CompareTo(stringB.ToString());
}
// Note: do error checking and consider i18n issues too :)
if (valueA[0] == valueB[0])
{
return int.Parse(valueA[1]).CompareTo(int.Parse(valueB[1]));
}
else
{
return int.Parse(valueA[0]).CompareTo(int.Parse(valueB[0]));
}
}
(Обратите внимание, что это не согласуется с вашим вопросом о том, что вы выполнили отладку и подтвердили, что Compare возвращает правильное значение, но я ' Боюсь, я подозреваю, что здесь произошла человеческая ошибка.)
Кроме того, Свен прав - изменение значения элементов
вообще не меняет ваш связанный список. Вы должны добавить:
this.Items = items;
внизу вашего метода.
Отсортированный список привязан только к элементам локальной переменной, а не к свойству Items вашего списка привязки, поэтому он остается несортированным.
[Edit] По сути, вы просто выбрасываете результат своих усилий по сортировке; -)
Я столкнулся с проблемой общей естественной сортировки и написал решение здесь:
Natural Sort Сравните с Linq OrderBy ()
public class NaturalSortComparer<T> : IComparer<string>, IDisposable
{
private bool isAscending;
public NaturalSortComparer(bool inAscendingOrder = true)
{
this.isAscending = inAscendingOrder;
}
#region IComparer<string> Members
public int Compare(string x, string y)
{
throw new NotImplementedException();
}
#endregion
#region IComparer<string> Members
int IComparer<string>.Compare(string x, string y)
{
if (x == y)
return 0;
string[] x1, y1;
if (!table.TryGetValue(x, out x1))
{
x1 = Regex.Split(x.Replace(" ", ""), "([0-9]+)");
table.Add(x, x1);
}
if (!table.TryGetValue(y, out y1))
{
y1 = Regex.Split(y.Replace(" ", ""), "([0-9]+)");
table.Add(y, y1);
}
int returnVal;
for (int i = 0; i < x1.Length && i < y1.Length; i++)
{
if (x1[i] != y1[i])
{
returnVal = PartCompare(x1[i], y1[i]);
return isAscending ? returnVal : -returnVal;
}
}
if (y1.Length > x1.Length)
{
returnVal = 1;
}
else if (x1.Length > y1.Length)
{
returnVal = -1;
}
else
{
returnVal = 0;
}
return isAscending ? returnVal : -returnVal;
}
private static int PartCompare(string left, string right)
{
int x, y;
if (!int.TryParse(left, out x))
return left.CompareTo(right);
if (!int.TryParse(right, out y))
return left.CompareTo(right);
return x.CompareTo(y);
}
#endregion
private Dictionary<string, string[]> table = new Dictionary<string, string[]>();
public void Dispose()
{
table.Clear();
table = null;
}
}