diff --git a/src/Discord.Net.Commands/Results/MatchResult.cs b/src/Discord.Net.Commands/Results/MatchResult.cs
new file mode 100644
index 000000000..fb266efa6
--- /dev/null
+++ b/src/Discord.Net.Commands/Results/MatchResult.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Discord.Commands
+{
+ public class MatchResult : IResult
+ {
+ ///
+ /// Gets the command that may have matched during the command execution.
+ ///
+ public CommandMatch? Match { get; }
+
+ ///
+ /// Gets on which pipeline stage the command may have matched or failed.
+ ///
+ public IResult? Pipeline { get; }
+
+ ///
+ public CommandError? Error { get; }
+ ///
+ public string ErrorReason { get; }
+ ///
+ public bool IsSuccess => !Error.HasValue;
+
+ private MatchResult(CommandMatch? match, IResult? pipeline, CommandError? error, string errorReason)
+ {
+ Match = match;
+ Error = error;
+ Pipeline = pipeline;
+ ErrorReason = errorReason;
+ }
+
+ public static MatchResult FromSuccess(CommandMatch match, IResult pipeline)
+ => new MatchResult(match,pipeline,null, null);
+ public static MatchResult FromError(CommandError error, string reason)
+ => new MatchResult(null,null,error, reason);
+ public static MatchResult FromError(Exception ex)
+ => FromError(CommandError.Exception, ex.Message);
+ public static MatchResult FromError(IResult result)
+ => new MatchResult(null, null,result.Error, result.ErrorReason);
+ public static MatchResult FromError(IResult pipeline, CommandError error, string reason)
+ => new MatchResult(null, pipeline, error, reason);
+
+ public override string ToString() => IsSuccess ? "Success" : $"{Error}: {ErrorReason}";
+ private string DebuggerDisplay => IsSuccess ? "Success" : $"{Error}: {ErrorReason}";
+
+ }
+}