public interface IString
{
string Content{ get;}
}
public class DString:IString
{
private readonly string content;
public string Content
{
get { return content; }
}
public DString(string content)
{
this.content = content;
}
}
public static class Class1
{
public static void Foo(params IString[] bars)
{
foreach (IString s in bars)
{
Console.WriteLine(s.Content);
}
}
public static void Foo<T>(T bar)
{
throw new NotImplementedException();
}
}
[TestFixture]
public class Tester
{
[Test]
public void CallBar()
{
Class1.Foo(new DString("baz"));
}
}
So what would you expect when running the unit test?
That's what I got:
TestCase 'ClassLibrary2.Tester.CallBar' failed: System.NotImplementedException : The method or operation is not implemented.
What happens here? If you add exactly one optional parameter, the compiler somehow thinks, you meant Foo<istring>() instead of Foo(). This happens only if the type parameter is an interface. I tried with string and that worked like expected, calling Foo().
So, is this a bug or a documented behaviour. Do you know ressources that document it? I didn't find any...
2007/11/09
WTF: Overloading and Generics
Recently I discovered some behaviour of .NET that I couldn't explain. I still wonder whether this is an error or "ByDesign". I found it when I tried to call ActiveRecordMediator's Exists method, which threw out an unexpected exception. Minutes later, I stared unbelievingly to the screen: A complete different method overload was called.
I sat down and created a short example that doesn't use ActiveRecord, so it can be understood from any .NET-developer:
Subscribe to:
Post Comments (Atom)
1 comment:
It's working as expected, but your explanation isn't what the compiler is doing.
Your call is Foo(x) where x is of compile-time type DString.
The choices are:
void Foo(params IString[] bars)
void Foo<T>(T bar)
Type inference determines that the second call is applicable, with T=DString. So in other words, you then have a situation similar to:
void Foo (params IString[] bars)
void Foo (DString bar)
and you're calling it with a single DString parameter.
Now which overload do you expect it to use? :)
Hope that helps,
Jon
Post a Comment