API's that Suck

December 10, 2009

Did you know overload resolution is broken in C#?

Filed under: Uncategorized — Grauenwolf @ 10:52 pm

Lets say you have this code:

  1. class Program
  2. {
  3.     static void Main()
  4.     {
  5.         Foo(new Giraffe());
  6.     }
  7.     static void Foo(Animal animal) { }
  8. }
  9.  
  10. class Animal { }
  11. class Mammal : Animal { }
  12. class Giraffe : Mammal { }
  13. class Reptile : Animal { }

So far so good. Now someone comes along and adds an overload to Foo specifically for Reptiles.

  1. static void Foo<T>(T t) where T : Reptile { }

What should happen? Well since Foo<T>(T) isn’t a viable candidate, it should continue to use Foo(Animal).

What actually happens is you get this error message.

The type ‘ConsoleApplication2.Giraffe’ cannot be used as type parameter ‘T’ in the generic type or method ‘ConsoleApplication2.Program.Foo<T>(T)’. There is no implicit reference conversion from ‘ConsoleApplication2.Giraffe’ to ‘ConsoleApplication2.Reptile’.

Eric Lippert tells us that the “constraints are not part of the signature”, which is of course easily verifiable. But then he goes on to say C# is correct in throwing a compiler error in this scenario because that’s what the C# specification says that it should do.

Lets see the same code in Visual Basic:

  1. Module Module1
  2.  
  3.     Sub Main()
  4.         Foo(New Giraffe)
  5.     End Sub
  6.  
  7.     Sub Foo(Of T As Reptile)(ByVal argt As T)
  8.     End Sub
  9.  
  10.     Sub Foo(ByVal animal As Animal)
  11.     End Sub
  12.  
  13. End Module
  14.  
  15. Class Animal : End Class
  16. Class Mammal : Inherits Animal : End Class
  17. Class Giraffe : Inherits Mammal : End Class
  18. Class Reptile : Inherits Animal : End Class

No errors here.

So yea, the C# compiler’s overload resolution code is broken. It may match the specification, but unless someone can come up with a really good reason for that behavior it just means the specification is also broken.

EDIT:

By the way, you can fix the C# code by explicit casting.

  1. Foo((Animal)new Giraffe());

Three sets of parens to VB’s one, that sounds about right.

About these ads

4 Comments »

  1. This is the correct behaviour: the best possible candidate is not viable, and the correct behaviour is for the compiler to inform the developer of this fact so that the developer can take action to ensure that the correct method is called.

    The fact that VB does something different is irrelevant. VB has different design criteria than C#. C# is designed to aggressively inform developers when a situation arises which might be an error. VB is designed to make a best guess as to what the developer meant. VB’s behaviour is correct for VB, and C#’s behaviour is correct for C#. Judging the behaviour of C# based on the VB design criteria, or vice versa, is judging apples by how orange they are.

    Comment by Eric Lippert — December 10, 2009 @ 11:37 pm

  2. Why is it that everyone always choose to go the “parentheses” route when comparing VB and C#. Hello ?! You mean the syntactical sugar in VB somehow gives it’s an advantage of some sort ? Enngh, I’ll take having the compiler squawk at me than something like being handled as “under the covers” as this is.

    Move along people, nothing to see. It’s just two compiler’s having a disagreement over the spelling of tomato ( and it’s “o”, not “oe”. ).

    Comment by Marcelo Lopez — December 11, 2009 @ 4:30 pm

    • For those who normally write in VB, the number one mistake when writing C# code is forgetting all the extra parentheses you need, especially around if statements and after method calls.

      Comment by grauenwolf — December 11, 2009 @ 6:34 pm

      • Oh, so it’s the whole “I don’t need no steenkin’ parentheses” excuses for not paying attention to what you’re doing ? Please….You mean like forgetting to capitalize practically every other verb, or adverb, when going from C# to VB. Oh that’s right, intelli….I mean IntelliSense does that for you, that’s right. Sorry that IntelliSense doesn’t force itself on you when switching from VB to C# that way. They’re different syntactical grammars. Hello ?!

        Comment by Marcelo Lopez — December 11, 2009 @ 6:58 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The WordPress Classic Theme Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: