CSharpFeeds - All your C# feeds in one place.

Sponsors

Monday, July 13, 2009

Evil Code of the Day: variance and overloading

by skeet via Jon Skeet: Coding Blog on 7/13/2009 4:10:00 PM

(Note that this kind of breakage was mentioned a long time ago in Eric Lippert's blog, although not in this exact form.)

Whenever a conversion becomes available where it wasn't before, overload resolution can change its behaviour. From C# 1 to C# 2 this happened due to delegate variance with method group conversions - now the same thing is true for generic variance for interfaces.

What does the following code print?

using System;
using System.Collections.Generic;

class Base
{
    public void Foo(IEnumerable<string> strings)
    {
        Console.WriteLine("Strings");
    }
}

class Derived : Base
{
    public void Foo(IEnumerable<object> objects)
    {
        Console.WriteLine("Objects");
    }
}

class Test
{
    static void Main()
    {
        List<string> strings = new List<string>();
        new Derived().Foo(strings);
    }
}

The correct answer is "it depends on which version of C# and .NET framework you're using."

If you're using C# 4.0 and .NET 4.0, then IEnumerable<T> is covariant: there's an implicit conversion from IEnumerable<string> to IEnumerable<object>, so the derived overload is used.

If you're using C# 4.0 but .NET 3.5 or earlier then the compiler still knows about variance in general, but the interface in the framework doesn't have the appropriate metadata to indicate it, so there's no conversion available, and the base class overload is used.

If you're using C# 3.0 or earlier then the compiler doesn't know about generic variance at all, so again the base class overload is used.

So, this is a breaking change, and a fairly subtle one at that - and unlike the method group conversion in .NET 2.0, the compiler in .NET 4.0 beta 1 doesn't issue a warning about it. I'll edit this post when there's an appropriate Connect ticket about it...

In general though, I'd say it's worth avoiding overloading a method declared in a base class unless you really have to. In particular, overloading it using the same number of parameters but more general ones seems to be a recipe for unreadable code.

email it!bookmark it!digg it!

Original Post: Evil Code of the Day: variance and overloading

Subscribe

New Feed

Product Spotlight

Recently Updated Sources

Legal Note

The content of the postings is owned by the respective author. CSharpFeeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on CSharpFeeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.

Advertise with us