diff --git a/Remora.Results.sln.DotSettings b/Remora.Results.sln.DotSettings
index cc1f393..cc4671d 100644
--- a/Remora.Results.sln.DotSettings
+++ b/Remora.Results.sln.DotSettings
@@ -122,10 +122,19 @@
<Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
+ <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy>
+ <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy>
+ <Policy><Descriptor Staticness="Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Instance fields (not private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Constant fields (not private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static fields (not private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static readonly fields (not private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy>
True
True
True
True
+ True
True
True
True
diff --git a/Remora.Results/AggregateResult.cs b/Remora.Results/AggregateResult.cs
new file mode 100644
index 0000000..e0d3450
--- /dev/null
+++ b/Remora.Results/AggregateResult.cs
@@ -0,0 +1,87 @@
+//
+// AggregateResult.cs
+//
+// Author:
+// Jarl Gullberg
+//
+// Copyright (c) Jarl Gullberg
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+using System.Collections.Generic;
+using System.Linq;
+using JetBrains.Annotations;
+
+namespace Remora.Results;
+
+///
+[PublicAPI]
+public readonly struct AggregateResult : IResult
+{
+ ///
+ /// Gets a value indicating whether all the contained results were successful.
+ ///
+ public bool IsSuccess { get; }
+
+ ///
+ /// Gets an containing the failed results.
+ ///
+ public IResultError Error => new AggregateError(_lookup[false].ToArray());
+
+ ///
+ ///
+ /// Always returns null.
+ ///
+ public IResult? Inner { get; } = null;
+
+ ///
+ /// Gets a collection of successful results.
+ ///
+ public IEnumerable SuccessfulResults => _lookup[true];
+
+ ///
+ /// Gets a collection of failed results.
+ ///
+ public IEnumerable FailedResults => _lookup[false];
+
+ ///
+ /// Gets a readonly collection of the results contained in this collection.
+ ///
+ public IReadOnlyCollection Results => _results;
+
+ private readonly IResult[] _results;
+ private readonly ILookup _lookup;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The results to use.
+ public AggregateResult(params IResult[] results)
+ : this(results.All(it => it.IsSuccess), results)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// A value indicating whether all the results are successful.
+ /// The results.
+ internal AggregateResult(bool isSuccess, IResult[] results)
+ {
+ this.IsSuccess = isSuccess;
+ _results = results;
+ _lookup = this.Results.ToLookup(it => it.IsSuccess);
+ }
+}
diff --git a/Remora.Results/AggregateResultBuilder.cs b/Remora.Results/AggregateResultBuilder.cs
new file mode 100644
index 0000000..2f70be9
--- /dev/null
+++ b/Remora.Results/AggregateResultBuilder.cs
@@ -0,0 +1,63 @@
+//
+// AggregateResultBuilder.cs
+//
+// Author:
+// Jarl Gullberg
+//
+// Copyright (c) Jarl Gullberg
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+using System.Collections.Generic;
+using JetBrains.Annotations;
+
+namespace Remora.Results;
+
+///
+/// Allows for the construction of an AggregateResult.
+///
+///
+/// This is intended for use within a foreach loop or in situations where results are added on their own
+/// rather than as a group. If you have all the results available together, use .
+///
+[PublicAPI]
+public class AggregateResultBuilder
+{
+ private List _results = new();
+ private bool _allSuccessful = true;
+
+ ///
+ /// Adds the result to the collection.
+ ///
+ /// The result to add.
+ public void Add(IResult result)
+ {
+ if (!result.IsSuccess)
+ {
+ _allSuccessful = false;
+ }
+
+ _results.Add(result);
+ }
+
+ ///
+ /// Builds the .
+ ///
+ /// A new AggregateResult.
+ public AggregateResult Build()
+ {
+ return new AggregateResult(_allSuccessful, _results.ToArray());
+ }
+}