Если у меня есть две коллекции типа T и IEqualityComparer, которые сравнивают подмножество их свойств, в какую из коллекции будут получены результирующие элементы Intersect или Union?Приоритет коллекции в LINQ Intersect, Union, используя IEqualityComparer
тестов я добежит предлагают следующее:
- товар (ов) из col1 выиграть
- если col1 или col2 содержат повторяющиеся элементы (как определен компаратором) внутри себя, выигрывает первая запись (внутри col1, затем col2).
Я знаю, что это не должно быть проблемой, поскольку (по определению) Я должен рассматривать результирующие объекты как равные. Мне просто пришло в голову, что использование Союза с пользовательским сопоставителем может быть немного более аккуратным, чем эквивалентный Join - хотя это справедливо только в том случае, если указанные предположения гарантированы.
class DummyComparer : IEqualityComparer<Dummy>
{
public bool Equals(Dummy x, Dummy y)
{
return x.ID == y.ID;
}
public int GetHashCode(Dummy obj)
{
return obj.ID.GetHashCode();
}
}
class Dummy
{
public int ID { get; set; }
public string Name { get; set; }
}
[Test]
public void UnionTest()
{
var comparer = new DummyComparer();
var d1 = new Dummy { ID = 0, Name = "test0" };
var d2 = new Dummy { ID = 0, Name = "test1" };
var d3 = new Dummy { ID = 1, Name = "test2" };
var d4 = new Dummy { ID = 1, Name = "test3" };
var col1 = new Dummy[] { d1, d3 };
var col2 = new Dummy[] { d2, d4 };
var x1 = col1.Union(col2, comparer).ToList();
var x2 = col2.Union(col1, comparer).ToList();
var y1 = col1.Except(col2, comparer).ToList();
var y2 = col2.Except(col1, comparer).ToList();
var z1 = col1.Intersect(col2, comparer).ToList();
var z2 = col2.Intersect(col1, comparer).ToList();
Assert.AreEqual(2, x1.Count);
Assert.Contains(d1, x1);
Assert.Contains(d3, x1);
Assert.AreEqual(2, x2.Count);
Assert.Contains(d2, x2);
Assert.Contains(d4, x2);
Assert.AreEqual(0, y1.Count);
Assert.AreEqual(0, y2.Count);
Assert.AreEqual(2, z1.Count);
Assert.Contains(d1, z1);
Assert.Contains(d3, z1);
Assert.AreEqual(2, z2.Count);
Assert.Contains(d2, z2);
Assert.Contains(d4, z2);
}
Я бы сказал, посмотрите на документацию MSDN, но на самом деле речь идет о 'Intersect'.Возможно, посмотрите [EduLinq] (http://msmvps.com/blogs/jon_skeet/archive/tags/Edulinq/default.aspx), он подробно рассказывает об исходных реализациях. – Rawling
@ Rawling: интересно, ты прав. Я посмотрел на «Intersect» с помощью ILSpy, и сначала он перечисляет вторую коллекцию, а затем первый, даже если задокументирован наоборот. Что может быть причиной? ** Изменить ** На самом деле Джон Скит также упомянул эту «ложь»: http://msmvps.com/blogs/jon_skeet/archive/2010/12/30/reimplementing-linq-to-objects-part-16-intersect- и-build-fiddling.aspx (по его словам: _ «Это явно неверно». _) –
@Tim. Также неоднозначно, какие элементы 'Intersect' возвращаются - я читал его как« маркирует элементы во второй последовательности и возвращает их ", но вы ясно читали это наоборот. (Да, это страница, о которой я думал, когда я связал EduLinq.) – Rawling