Это простой способ сделать это, который имеет дополнительное преимущество работы как в LINQ над объектами и LINQ над SQL:
var q1=a1.Where(a=>!a2.Any(b=>b.Id==a.Id));
var q2=a2.Where(a=>!a1.Any(b=>b.Id==a.Id));
var a3=a1.Where(a=>a2.Any(b=>b.Id==a.Id));
От LINQPad:
class Anime
{
public int Id { get; set; }
public string Title { get; set; }
public string ImageUrl { get; set; }
}
void Main()
{
var a1=new Anime[]{new Anime {Id=1,Title="Title1"},new Anime {Id=2,Title="Title2"}};
var a2=new Anime[]{new Anime {Id=2,Title="Title2"},new Anime {Id=3,Title="Title3"}};
var q1=a1.Where(a=>!a2.Any(b=>b.Id==a.Id));
var q2=a2.Where(a=>!a1.Any(b=>b.Id==a.Id));
var q3=a1.Where(a=>a2.Any(b=>b.Id==a.Id));
q1.Dump();
q2.Dump();
q3.Dump();
}
Результат:
Вы также можете настроить пользовательский IEqualityComp ARER и использовать пересекающей, но это, как правило, гораздо сложнее, чем это стоит во всех, кроме высокой производительности ситуациях, и не работает с LINQ над SQL:
class Anime
{
public int Id { get; set; }
public string Title { get; set; }
public string ImageUrl { get; set; }
}
class AnimeComparer: IEqualityComparer<Anime>
{
public bool Equals(Anime a1, Anime a2)
{
return (a1.Id==a2.Id);
}
public int GetHashCode(Anime a)
{
return a.Id.GetHashCode();
}
}
void Main()
{
var a1=new Anime[]{new Anime {Id=1,Title="Title1"},new Anime {Id=2,Title="Title2"}};
var a2=new Anime[]{new Anime {Id=2,Title="Title2"},new Anime {Id=3,Title="Title3"}};
var ac=new AnimeComparer();
var q1=a1.Except(a2,ac);
var q2=a2.Except(a1,ac);
var q3=a1.Intersect(a2,ac);
q1.Dump();
q2.Dump();
q3.Dump();
}
Третий подход заключается в использовании метода расширения. Это также не будет, вероятно, работать с LINQ над SQL, но не требует модификации любых классов, или пользовательские IEqualityComparers, если у вас есть большое разнообразие типов объектов:
public static class LinqExtensions
{
public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, TSource, bool> comparer)
{
return first.Where(x => !second.Any(y => comparer(x, y)));
}
public static IEnumerable<TSource> Intersect<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, TSource, bool> comparer)
{
return first.Where(x => second.Any(y => comparer(x, y)));
}
}
class Anime
{
public int Id { get; set; }
public string Title { get; set; }
public string ImageUrl { get; set; }
}
void Main()
{
var a1=new Anime[]{new Anime {Id=1,Title="Title1"},new Anime {Id=2,Title="Title2"}};
var a2=new Anime[]{new Anime {Id=2,Title="Title2"},new Anime {Id=3,Title="Title3"}};
var q1=a1.Except(a2,(b1,b2)=>b1.Id==b2.Id);
var q2=a2.Except(a1,(b1,b2)=>b1.Id==b2.Id);
var q3=a1.Intersect(a2,(b1,b2)=>b1.Id==b2.Id);
q1.Dump();
q2.Dump();
q3.Dump();
}
Четвертый вариант заключается в использовании morelinq, который сочетает в себе простоту без какого-либо пользовательского IEqualityComparers с очень высокой производительностью (но не совместимой с LINQ над SQL):
class Anime
{
public int Id { get; set; }
public string Title { get; set; }
public string ImageUrl { get; set; }
}
void Main()
{
var a1=new Anime[]{new Anime {Id=1,Title="Title1"},new Anime {Id=2,Title="Title2"}};
var a2=new Anime[]{new Anime {Id=2,Title="Title2"},new Anime {Id=3,Title="Title3"}};
var q1=a1.ExceptBy(a2,k=>k.Id);
var q2=a2.ExceptBy(a1,k=>k.Id);
var q3=a1.ExceptBy(q1,k=>k.Id);
q1.Dump();
q2.Dump();
q3.Dump();
}
См 'IEnumerable' методы, такие как Intersect, за исключением, Союза –
EZI
и создать 'IComparer' для' Anime' типа. –