Set operations (C#)
Set operations in LINQ refer to query operations that produce a result set that is based on the presence or absence of equivalent elements within the same or separate collections (or sets).
The standard query operator methods that perform set operations are listed in the following section.
Methods
| Method names | Description | C# query expression syntax | More information |
|---|---|---|---|
| Distinct or DistinctBy | Removes duplicate values from a collection. | Not applicable. | Enumerable.Distinct Enumerable.DistinctBy Queryable.Distinct Queryable.DistinctBy |
| Except or ExceptBy | Returns the set difference, which means the elements of one collection that do not appear in a second collection. | Not applicable. | Enumerable.Except Enumerable.ExceptBy Queryable.Except Queryable.ExceptBy |
| Intersect or IntersectBy | Returns the set intersection, which means elements that appear in each of two collections. | Not applicable. | Enumerable.Intersect Enumerable.IntersectBy Queryable.Intersect Queryable.IntersectBy |
| Union or UnionBy | Returns the set union, which means unique elements that appear in either of two collections. | Not applicable. | Enumerable.Union Enumerable.UnionBy Queryable.Union Queryable.UnionBy |
Examples
Some of the following examples rely on a record type that represents the planets in our solar system.
namespace SolarSystem;
record Planet(
string Name,
PlanetType Type,
int OrderFromSun)
{
public static readonly Planet Mercury =
new(nameof(Mercury), PlanetType.Rock, 1);
public static readonly Planet Venus =
new(nameof(Venus), PlanetType.Rock, 2);
public static readonly Planet Earth =
new(nameof(Earth), PlanetType.Rock, 3);
public static readonly Planet Mars =
new(nameof(Mars), PlanetType.Rock, 4);
public static readonly Planet Jupiter =
new(nameof(Jupiter), PlanetType.Gas, 5);
public static readonly Planet Saturn =
new(nameof(Saturn), PlanetType.Gas, 6);
public static readonly Planet Uranus =
new(nameof(Uranus), PlanetType.Liquid, 7);
public static readonly Planet Neptune =
new(nameof(Neptune), PlanetType.Liquid, 8);
// Yes, I know... not technically a planet anymore
public static readonly Planet Pluto =
new(nameof(Pluto), PlanetType.Ice, 9);
}
The record Planet is a positional record, which requires a Name, Type, and OrderFromSun arguments to instantiate it. There are several static readonly planet instances on the Planet type. These are convenience-based definitions for well-known planets. The Type member identifies the planet type.
namespace SolarSystem;
enum PlanetType
{
Rock,
Ice,
Gas,
Liquid
};
Distinct and DistinctBy
The following example depicts the behavior of the Enumerable.Distinct method on a sequence of strings. The returned sequence contains the unique elements from the input sequence.

string[] planets = { "Mercury", "Venus", "Venus", "Earth", "Mars", "Earth" };
IEnumerable<string> query = from planet in planets.Distinct()
select planet;
foreach (var str in query)
{
Console.WriteLine(str);
}
/* This code produces the following output:
*
* Mercury
* Venus
* Earth
* Mars
*/
The DistinctBy is an alternative approach to Distinct that takes a keySelector. The keySelector is used as the comparative discriminator of the source type. Consider the following planet array:
Planet[] planets =
{
Planet.Mercury,
Planet.Venus,
Planet.Earth,
Planet.Mars,
Planet.Jupiter,
Planet.Saturn,
Planet.Uranus,
Planet.Neptune,
Planet.Pluto
};
In the following code, planets are discriminated based on their PlanetType, and the first planet of each type is displayed:
foreach (Planet planet in planets.DistinctBy(p => p.Type))
{
Console.WriteLine(planet);
}
// This code produces the following output:
// Planet { Name = Mercury, Type = Rock, OrderFromSun = 1 }
// Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
// Planet { Name = Uranus, Type = Liquid, OrderFromSun = 7 }
// Planet { Name = Pluto, Type = Ice, OrderFromSun = 9 }
In the preceding C# code:
- The
Planetarray is filtered distinctly to the first occurrence of each unique planet type. - The resulting
planetinstances are written to the console.
Except and ExceptBy
The following example depicts the behavior of Enumerable.Except. The returned sequence contains only the elements from the first input sequence that are not in the second input sequence.

string[] planets1 = { "Mercury", "Venus", "Earth", "Jupiter" };
string[] planets2 = { "Mercury", "Earth", "Mars", "Jupiter" };
IEnumerable<string> query = from planet in planets1.Except(planets2)
select planet;
foreach (var str in query)
{
Console.WriteLine(str);
}
/* This code produces the following output:
*
* Venus
*/
The ExceptBy method is an alternative approach to Except that takes two sequences of possibly heterogenous types and a keySelector. The keySelector is the same type as the second collection's type, and it is used as the comparative discriminator of the source type. Consider the following planet arrays:
Planet[] planets =
{
Planet.Mercury,
Planet.Venus,
Planet.Earth,
Planet.Jupiter
};
Planet[] morePlanets =
{
Planet.Mercury,
Planet.Earth,
Planet.Mars,
Planet.Jupiter
};
To find planets in the first collection that aren't in the second collection, you can project the planet names as the second collection and provide the same keySelector:
// A shared "keySelector"
static string PlanetNameSelector(Planet planet) => planet.Name;
foreach (Planet planet in
planets.ExceptBy(
morePlanets.Select(PlanetNameSelector), PlanetNameSelector))
{
Console.WriteLine(planet);
}
// This code produces the following output:
// Planet { Name = Venus, Type = Rock, OrderFromSun = 2 }
In the preceding C# code:
- The
keySelectoris defined as astaticlocal function that discriminates on a planet name. - The first planet array is filtered to planets that are not found in the second planet array, based on their name.
- The resulting
planetinstance is written to the console.
Intersect and IntersectBy
The following example depicts the behavior of Enumerable.Intersect. The returned sequence contains the elements that are common to both of the input sequences.

string[] planets1 = { "Mercury", "Venus", "Earth", "Jupiter" };
string[] planets2 = { "Mercury", "Earth", "Mars", "Jupiter" };
IEnumerable<string> query = from planet in planets1.Intersect(planets2)
select planet;
foreach (var str in query)
{
Console.WriteLine(str);
}
/* This code produces the following output:
*
* Mercury
* Earth
* Jupiter
*/
The IntersectBy method is an alternative approach to Intersect that takes two sequences of possibly heterogenous types and a keySelector. The keySelector is used as the comparative discriminator of the second collection's type. Consider the following planet arrays:
Planet[] firstFivePlanetsFromTheSun =
{
Planet.Mercury,
Planet.Venus,
Planet.Earth,
Planet.Mars,
Planet.Jupiter
};
Planet[] lastFivePlanetsFromTheSun =
{
Planet.Mars,
Planet.Jupiter,
Planet.Saturn,
Planet.Uranus,
Planet.Neptune
};
There are two arrays of planets; one represents the first five planets from the sun and the second represents the last five planets from the sun. Since the Planet type is a positional record type, you can use its value comparison semantics in the form of the keySelector:
foreach (Planet planet in
firstFivePlanetsFromTheSun.IntersectBy(
lastFivePlanetsFromTheSun, planet => planet))
{
Console.WriteLine(planet);
}
// This code produces the following output:
// Planet { Name = Mars, Type = Rock, OrderFromSun = 4 }
// Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
In the preceding C# code:
- The two
Planetarrays are intersected by their value comparison semantics. - Only planets that are found in both arrays are present in the resulting sequence.
- The resulting
planetinstances are written to the console.
Union and UnionBy
The following example depicts a union operation on two sequences of strings. The returned sequence contains the unique elements from both input sequences.

string[] planets1 = { "Mercury", "Venus", "Earth", "Jupiter" };
string[] planets2 = { "Mercury", "Earth", "Mars", "Jupiter" };
IEnumerable<string> query = from planet in planets1.Union(planets2)
select planet;
foreach (var str in query)
{
Console.WriteLine(str);
}
/* This code produces the following output:
*
* Mercury
* Venus
* Earth
* Jupiter
* Mars
*/
The UnionBy method is an alternative approach to Union that takes two sequences of the same type and a keySelector. The keySelector is used as the comparative discriminator of the source type. Consider the following planet arrays:
Planet[] firstFivePlanetsFromTheSun =
{
Planet.Mercury,
Planet.Venus,
Planet.Earth,
Planet.Mars,
Planet.Jupiter
};
Planet[] lastFivePlanetsFromTheSun =
{
Planet.Mars,
Planet.Jupiter,
Planet.Saturn,
Planet.Uranus,
Planet.Neptune
};
To union these two collections into a single sequence, you provide the keySelector:
foreach (Planet planet in
firstFivePlanetsFromTheSun.UnionBy(
lastFivePlanetsFromTheSun, planet => planet))
{
Console.WriteLine(planet);
}
// This code produces the following output:
// Planet { Name = Mercury, Type = Rock, OrderFromSun = 1 }
// Planet { Name = Venus, Type = Rock, OrderFromSun = 2 }
// Planet { Name = Earth, Type = Rock, OrderFromSun = 3 }
// Planet { Name = Mars, Type = Rock, OrderFromSun = 4 }
// Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
// Planet { Name = Saturn, Type = Gas, OrderFromSun = 6 }
// Planet { Name = Uranus, Type = Liquid, OrderFromSun = 7 }
// Planet { Name = Neptune, Type = Liquid, OrderFromSun = 8 }
In the preceding C# code:
- The two
Planetarrays are weaved together using theirrecordvalue comparison semantics. - The resulting
planetinstances are written to the console.
See also
Tilbakemeldinger
Send inn og vis tilbakemelding for