Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider allowing implicit operators in a throw statement #9971

Closed
hughbe opened this issue Mar 22, 2016 · 5 comments
Closed

Consider allowing implicit operators in a throw statement #9971

hughbe opened this issue Mar 22, 2016 · 5 comments
Labels
Area-Language Design Discussion Feature Request Resolution-Won't Fix A real bug, but Triage feels that the issue is not impactful enough to spend time on.

Comments

@hughbe
Copy link

hughbe commented Mar 22, 2016

Example problem

enum ErrorType { Case1, Case2... }

class DerivedException : Exception 
{
    public ErrorType Error { get; }
    public DerivedException(ErrorType error) { Error = error; }

    public static implicit operator DerivedException (Error error) => new DerivedException (error);
}

void MethodThatThrows()
{
    // Doesn't work: "The type caught or thrown must be derived from System.Exception"
    throw ErrorType.Case2;
}

The above is quite a nice way of throwing an error, and is quite descriptive as it provides context to what you're throwing.

However, this doesn't work, due to the error above.

Proposition

Modify the type checking and generation of the throw statement to implicitly convert a type to Exception if it is possible.
This behaviour is quite similar to Swift, I think.

Currently, the alternative is

DerivedException ex = ErrorType.Case1;
throw ex;

Unfortunately, this is ugly and doesn't offer any advantage from the implicit cast

@HaloFour
Copy link

To note, Swift's syntax isn't because it's exception types are any different, it's because Swift's enums are actually classes. You'll notice that it's illegal to throw a class or enum value in Swift unless it inherits from ErrorType which is Swift's version of Exception.

I personally don't see much issue in allowing throw to attempt an implicit conversion from whatever the type of the expression happens to be into an Exception.

However, the way you have that implicit conversion I think would make that really complicated and confusing. When performing an implicit cast the C# knows exactly which type the expression is being converted from and converted to. This limits the scope of types in which the compiler will scan for potential conversion operators. With your use case above the compiler would only have half of that information. The compiler would be required to scan literally every referenced class that derives from Exception to look for possible conversion operators. What if there are two different exception classes that offer operators to convert from ErrorType to some kind of exception? The compiler would never be able to disambiguate those options.

TL;DR, assuming it wouldn't introduce other ambiguities in syntax, I would be all for allowing for implicit conversions using operators defined in the source type. However given that the compiler would have no idea which type of exception should be thrown that it doesn't make sense to have the compiler support an implicit operator defined in the target Exception type.

@hughbe
Copy link
Author

hughbe commented Mar 23, 2016

@HaloFour thanks for the comments

I don't actually propose a swift like system, I'm just saying that if C# supports implicit conversion of types, then we should be able to throw an implicitly converted exception

@HaloFour
Copy link

@hughbe

I don't actually propose a swift like system

Yes, I just wanted to point out that difference. Although #6739 might bring that syntax into C#.

I'm just saying that if C# supports implicit conversion of types, then we should be able to throw an implicitly converted exception

Sure, and I somewhat agree. If you had an implicit conversion operator declared in your ErrorType enum to Exception then I think that it would make sense to allow throwing an ErrorType and have the C# compiler resolve that implicit operator. I know that this isn't possible with enums.

However, in your use case there's nothing to hint to the C# compiler that what you want is a DerivedException so there's no way that the C# compiler knows to look for conversion operators in the DerivedException class.

This issue isn't unique to Exception. The C# compiler never scans all derived types of a given class to find potential conversion operators. The following is also a compiler error:

public class Foo { }
public class Bar : Foo {
    public static implicit operator Bar(string value) {
        return new Bar();
    }
}

static class Program {
    static void Main() {
        Foo foo = "Hello"; // CS0029: Cannot implicitly convert type 'string' to 'Foo'
        Bar bar = "World"; // just fine
    }
}

@gafter
Copy link
Member

gafter commented Mar 23, 2016

Modify the type checking and generation of the throw statement to implicitly convert a type to Exception if it is possible.

As has been noted, the proposed change would not affect the use case in the original issue. The original use case has no user-defined conversion from ErrorType to Exception. It would, however, affect this use case:

class Program
{
    static void Main(string[] args)
    {
        Foo foo = null;
        throw foo;
    }
}

class Foo
{
    public static implicit operator Exception(Foo self) { return null; }
}

@HaloFour
Copy link

Adding static methods to an enum would be nice, then ErrorType could define an implicit conversion operator to Exception. I understand that would require modifications to the CLR.

Maybe with #5165 / #4945 you could define an extension implicit conversion operator from ErrorType to Exception.

@gafter gafter added the Resolution-Won't Fix A real bug, but Triage feels that the issue is not impactful enough to spend time on. label Mar 25, 2016
@gafter gafter closed this as completed Mar 25, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Language Design Discussion Feature Request Resolution-Won't Fix A real bug, but Triage feels that the issue is not impactful enough to spend time on.
Projects
None yet
Development

No branches or pull requests

3 participants