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

Why a casting exception is thrown at runtime instead of handled at compile time for variance mis-match #8664

Closed
scionwest opened this issue Feb 13, 2016 · 4 comments
Labels
Area-Language Design Feature Request Resolution-Won't Fix A real bug, but Triage feels that the issue is not impactful enough to spend time on.

Comments

@scionwest
Copy link

I'm not sure if this is a bug, or by design, as it's existed for a while (forever?) in C#. If I have a method called GetFoo() that returns an IEnumerable<IFoo>, then the following code will fail despite FooBarimplementing IFoo

IEnumerable<FooBar> fooBar = GetFoo();

This gives the correct compiler error of

Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<Variance.IBar>' to 'System.Collections.Generic.IEnumerable<Variance.FooBar>'. An explicit conversion exists (are you missing a cast?)

However, if I use the GetFoo() method in a foreach loop, where each element is of Type FooBar, there are no compiler errors. Instead, a runtime exception is thrown.

// No compiler error
foreach(FooBar element in GetFoo())
{
    Console.WriteLine(element.DoBar());
}

The compiler can tell that the Type specified on the left side, can not be safely cast to the IBar returned on the right side of the expression. Shouldn't it have a compiler error to state this?

I can see this being a nice feature, if the developer can 100% with certainty know that GetFoo() will return every element as FooBar; that feels unsafe to me in a language that has strong roots in Type safety.

I have an example that reproduces this if anyone wants to clone and run it.

@scionwest scionwest changed the title Why a contravariance exception is thrown at runtime instead of handled at compile time Why a casting exception is thrown at runtime instead of handled at compile time for variance mis-match Feb 13, 2016
@HaloFour
Copy link

Thought it might be a relic from the days prior to generics but the emitted IL is definitely using the generic interfaces and attempting to downcast. Perhaps a concession prior to variance. Either way it seems to be a common law feature now and probably would be considered a breaking change to resolve as suggested.

@scionwest
Copy link
Author

Providing a warning that it wasn't safe, like unused variables and other warnings wouldn't be breaking and provide a valuable safety check.

The other option would be for Visual Studio to handle it with the Roslyn API and give a fix suggestion

@HaloFour
Copy link

@scionwest I'd agree, but in a couple of other cases where adding a warning has been suggested it was considered a breaking change as it would break builds that treat warnings as errors. The proposal #1580 seeks to address this better.

@gafter
Copy link
Member

gafter commented Feb 15, 2016

Making this an error would be a breaking change.

@gafter gafter closed this as completed Feb 15, 2016
@gafter gafter added Resolution-Won't Fix A real bug, but Triage feels that the issue is not impactful enough to spend time on. Feature Request Area-Language Design labels Feb 15, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Language Design 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