runtime: Proposal: MatchFailureException

Rationale

In order to facilitate the language feature at https://github.com/dotnet/csharplang/issues/45, which has been approved by the LDM and mostly implemented, we should add the exception MatchFailureException to the framework. This exception is to be thrown when no branch of a pattern-matching switch expression matches the input at runtime.

Proposal

namespace System
{
    /// <summary>
    /// Indicates that a switch expression that was non-exhaustive failed to match its input
    /// at runtime, e.g. in the C# 8 expression <code>3 switch { 4 => 5 }</code>.
    /// The exception optionally contains an object representing the unmatched value.
    /// </summary>
    [System.Runtime.InteropServices.ComVisible(true)]
    [Serializable]
    public class MatchFailureException : InvalidOperationException
    {
        public MatchFailureException();
        public MatchFailureException(object unmatchedValue);
        public object UnmatchedValue { get; }
        [System.Security.SecurityCritical]
        public override void GetObjectData(SerializationInfo info, StreamingContext context);
    }
}

See also https://github.com/dotnet/roslyn/issues/27747 /cc @jcouv @jaredpar

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 37 (30 by maintainers)

Commits related to this issue

Most upvoted comments

I changed the base type to InvalidOperationException.

@maryamariyan can you please add this new exception next week? Looks like it’s super easy, API is approved, basically no code (like eg InvalidDataException) except for this object getter, basic tests to new it up and get/set.

@gafter @terrajobst are [System.Security.SecurityCritical] and [ComVisible(true)] both required? SecurityCritical has no effect in .NET Core and no other exceptions have it. No other exceptions have ComVisible(true) either.

If you catch the excepetion (using the type InvalidOperationException) on .NET Core 2.x, your code will also catch the exception on .NET Core 3.x, as MatchFailureException is derived from InvalidOperationException.

Ah, I missed the inheritance relationship. That addresses my concern.

It seems (at least to me) that he unmatchedValue isn’t a good idea if it can’t be used in all cases, such as ref structs (because it means developers have to read the message and check the source code anyway).

FWIW, I pushed for this to be included because it can only help with debugging, and in most cases it should be able to include the value (it won’t in corner cases like matching on a ref struct). The value’s ToString would be output as part of Exception’s ToString, similar to how it is for ArgumentOutOfRangeException.

When would the compiler omit it?

e.g. if it’s something that can’t be boxed, like a ref struct

I’ve added an (optional) object unmatchedValue parameter.