Let's do some fancy set operations using the new `UnionBy()`, `IntersectBy()`, `ExceptBy()`, and `DistinctBy()` methods in .NET 6!

## Current Implementation

.NET 5 and below include operations in LINQ that are collectively called set operations; that is, they operate on sets of values compared to other sets of values.

For example, the `Union()` method produces the set union by combining all values from two sets, while removing the duplicates.

``````var numbers1 = new List<int>() {2, 5, 6, 9};
var numbers2 = new List<int>() {5, 8, 10};

var union = numbers1.Union(numbers2);
//2, 5, 6, 9, 8, 10``````

The `Intersect()` method produces the values that appear in both the sets.

``````var numbers1 = new List<int>() {2, 5, 6, 9};
var numbers2 = new List<int>() {5, 8, 10};

var intersect = numbers1.Intersect(numbers2);
//5``````

The `Except()` method gives the numbers that only appear in the first set, and do not appear in the second set.

``````var numbers1 = new List<int>() {2, 5, 6, 9};
var numbers2 = new List<int>() {5, 8, 10};

var except = numbers1.Except(numbers2);
//2, 6, 9``````

Finally, the `Distinct()` method operates on a single set and gives the distinct values from within that set.

``````var numbers = new List<int>() {6, 1, 6, 7, 1, 8, 1, 2, 3, 2};

var distinct = numbers.Distinct();
//7, 8, 3``````

Just like we saw in the previous post about `MaxBy()` and `MinBy()`, these kinds of operations are great if you are only working with primitive types. But what if you need to work with complex collections of classes? .NET 6 includes a new set of methods in the LINQ library to help with those situations.

## New Implementation

Let's say we have the `User` class from the previous post, and two collections of users.

### UnionBy

We can use the new `UnionBy()` method to do a complex calculation: get users from both sets who have distinct birth years. This calculation "favors" the first set, because if users in the second set have the same birth year as users in the first set, the users from the first set will be included and the users from the second set will not.

### IntersectBy

The `IntersectBy()` method can be used to find users who do not share a birth year with anyone from the opposite set.

### ExceptBy

What if we wanted to find all users in both sets, except those who have particular first names? We can do that using `ExceptBy()`.

``````public void Examples()
{
List<User> users = GetUserList();
var users2 = GetUserList2();

var names = new List<string>() { "Hailee", "Jackson", "Jeremy" };
var exceptByFirstName = users.ExceptBy(names, x => x.FirstName);

//Terrance Johnson
//Angelica Johnson
//Toni Berkowitz
//Vanessa Warren
//Lawrence Neilson
}``````

### DistinctBy

Finally, we can do things like "get all users by distinct birth dates" using `DistinctBy()`:

## Other Considerations

With these methods, order of invocation matters. For example, consider the following code, which is nearly the same as the earlier use of `IntersectBy()` with two small changes.

``````public void Examples()
{
var users = GetUserList();
var users2 = GetUserList2();

var intersectionBirthYear
= users2.IntersectBy(users.Select(x => x.DateOfBirth.Year),
x => x.DateOfBirth.Year);
//Jeremy Yardling
//Toni Berkowitz
//Vanessa Warren
//Lawrence Neilson
}``````

Because `users2` is now the "primary" set, we get a completely different result set than in the earlier example. Be careful with your order of invocation!

## Demo Project

As with all posts in this series, there is a demo project you can check out over on GitHub with the examples for `UnionBy()`, `IntersectBy()`, `DistinctBy()`, and `ExceptBy()` found in this post. Check it out!

Happy Coding!