Consider the following class,
class Foo
{
public Foo(int count)
{
/* .. */
}
public Foo(int count)
{
/* .. */
}
}
Above code is invalid and won't compile. Now consider the following code,
class Foo<T>
{
public Foo(int count)
{
/* .. */
}
public Foo(T t)
{
/* .. */
}
}
static void Main(string[] args)
{
Foo<int> foo = new Foo<int>(1);
}
Above code is valid and compiles well. It calls Foo(int count).
My question is, if the first one is invalid, how can the second one be valid? I know class Foo<T> is valid because T and int are different types. But when it is used like Foo<int> foo = new Foo<int>(1), T is getting integer type and both constructor will have same signature right? Why don't compiler show error rather than choosing an overload to execute?
There is no ambiguity, because the compiler will choose the most specific overload of Foo(...) that matches. Since a method with a generic type parameter is considered less specific than a corresponding non-generic method, Foo(T) is therefore less specific than Foo(int) when T == int. Accordingly, you are invoking the Foo(int) overload.
Your first case (with two Foo(int) definitions) is an error because the compiler will allow only one definition of a method with precisely the same signature, and you have two.
Your question was hotly debated when C# 2.0 and the generic type system in the CLR were being designed. So hotly, in fact, that the "bound" C# 2.0 specification published by A-W actually has the wrong rule in it! There are four possibilities:
1) Make it illegal to declare a generic class that could POSSIBLY be ambiguous under SOME construction. (This is what the bound spec incorrectly says is the rule.) So your Foo<T> declaration would be illegal.
2) Make it illegal to construct a generic class in a manner which creates an ambiguity. declaring Foo<T> would be legal, constructing Foo<double> would be legal, but constructing Foo<int> would be illegal.
3) Make it all legal and use overload resolution tricks to work out whether the generic or nongeneric version is better. (This is what C# actually does.)
4) Do something else I haven't thought of.
Rule #1 is a bad idea because it makes some very common and harmless scenarios impossible. Consider for example:
class C<T>
{
public C(T t) { ... } // construct a C that wraps a T
public C(Stream state) { ... } // construct a C based on some serialized state from disk
}
You want that to be illegal just because C<Stream> is ambiguous? Yuck. Rule #1 is a bad idea, so we scrapped it.
Unfortunately, it is not as simple as that. IIRC the CLI rules say that an implementation is allowed to reject as illegal constructions that actually do cause signature ambiguities. That is, the CLI rules are something like Rule #2, whereas C# actually implements Rule #3. Which means that there could in theory be legal C# programs that translate into illegal code, which is deeply unfortunate.
For some more thoughts on how these sorts of ambiguities make our lives wretched, here are a couple of articles I wrote on the subject:
http://blogs.msdn.com/ericlippert/archive/2006/04/05/569085.aspx
http://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx
Eric Lippert blogged about this recently.
The fact is that they do not both have the same signature - one is using generics while this other is not.
With those methods in place you could also call it using a non-int object:
Foo<string> foo = new Foo<string>("Hello World");
Related
UPDATE: As of C# 7.3, this should no longer be an issue. From the release notes:
When a method group contains some generic methods whose type arguments do not satisfy their constraints, these members are removed from the candidate set.
Pre C# 7.3:
So I read Eric Lippert's 'Constraints are not part of the signature', and now I understand that the spec specifies that type constraints are checked AFTER overload resolution, but I'm still not clear on why this MUST be the case. Below is Eric's example:
static void Foo<T>(T t) where T : Reptile { }
static void Foo(Animal animal) { }
static void Main()
{
Foo(new Giraffe());
}
This doesn't compile because overload resolution for: Foo(new Giraffe()) infers that Foo<Giraffe> is the best overload match but then the type constraints fail and a compile-time error is thrown. In Eric's words:
The principle here is overload resolution (and method type inference) find the best possible match between a list of arguments and each candidate method’s list of formal parameters. That is, they look at the signature of the candidate method.
Type constraints are NOT part of the signature, but why can't they be? What are some scenarios where it is a bad idea to consider type constraints part of the signature? Is it just difficult or impossible to implement? I'm not advocating that if the best chosen overload is for whatever reason impossible to call then silently fallback to the second best; I would hate that. I'm just trying to understand why type constraints can't be used to influence the choosing of the best overload.
I'm imagining that internally in the C# compiler, for overload resolution purposes only (it doesn't permanently rewrite the method), the following:
static void Foo<T>(T t) where T : Reptile { }
gets transformed to:
static void Foo(Reptile t) { }
Why can't you sort of "pull in" the type constraints into the formal parameter list? How does this change the signature in any bad way? I feel like it only strengthens the signature. Then Foo<Reptile> will never be considered as an overload candidate.
Edit 2: No wonder my question was so confusing. I didn't properly read Eric's blog and I quoted the wrong example. I've edited in the example I think more appropriate. I've also changed the title to be more specific. This question doesn't seem as simple as I first imagined, perhaps I'm missing some important concept. I'm less sure that this is stackoverflow material, it may be best for this question/discussion to be moved elsewhere.
The C# compiler has to not consider type constraints as part as the method signature because they are not part of the method signature for the CLR. It would be disastrous if the overload resolution worked differently for different languages (mainly due to the dynamic binding that may happen at runtime and should not be different from one language to another, or else all hells would break loose).
Why was it decided that these constraints would not be part of the method signature for the CLR is another question alltogether, and I could only make ill informed suppositions about that. I'll let the people in the know answer that.
If T matches multiple constraints, you create an ambiguity that cannot be automatically resolved. For example you have one generic class with the constraint
where T : IFirst
and another with the constraint
where T : ISecond
You now want T to be a class that implements both IFirst and ISecond.
Concrete code example:
public interface IFirst
{
void F();
}
public interface ISecond
{
void S();
}
// Should the compiler pick this "overload"?
public class My<T> where T : IFirst
{
}
// Or this one?
public class My<T> where T : ISecond
{
}
public class Foo : IFirst, ISecond
{
public void Bar()
{
My<Foo> myFoo = new My<Foo>();
}
public void F() { }
public void S() { }
}
I've been feeling my way around the C# compiler with it's limits of "inherited instantiated generic classes".
Anyway, This is my test case:
class Program
{
static void Main(string[] args)
{
var x = new InClass();
Console.WriteLine(x.Test(10)); //prints foo
Console.ReadLine();
}
}
class BaseClass<Foo, Bar>
{
public virtual Foo Test(Bar b)
{
return default(Foo);
}
public virtual string Test(int b)
{
return "foo"; ;
}
}
class InClass : BaseClass<string, int>
{
/*public override string Test(int b)
{
return "bar";
}*/
}
I would think that this declaration of InClass would throw a compiler error, as it makes Test ambiguous. It also makes the non-generic Test impossible to call within the InClass. Notice I have some code commented out in InClass as well. If I uncomment that code, I do get a compiler error.
Is there a mention of this behavior at all in the C# spec, or is this an unheard of edge case?
I would think that this declaration of InClass would throw a compiler error, as it makes Test ambiguous.
Nope. The specification calls out this kind of thing explicitly in section 7.5.3.6:
While signatures as declared must be unique, it is possible that substitution of type arguments might result in identical signatures. In such cases, the tie-breaking rules of overload resolution above will pick the most specific member.
The following examples show overloads that are valid and invalid according to this rule.
(Examples follow, obviously.)
So the language designers have considered it, but presumably the alternatives would be worse. (It would be annoying to not be able to create a class such as InClass even when you didn't want to call Test, for example.)
See this related question:
Why aren't generic type constraints inheritable/hierarchically enforced
Eric Lippert provides a thorough exploration of the potential implications.
The inherited generic types are not enforced by the compiler because they dev team felt it was a rabbit hole not worth going down.
My guess is that method with (int x) signature is better match for int argument than one with generic type Bar that happens to be int in this particular case.
While refactoring some code, I came across this strange compile error:
The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments.
It seems to occur when trying to call base methods/constructors that take dynamic arguments. For example:
class ClassA
{
public ClassA(dynamic test)
{
Console.WriteLine("ClassA");
}
}
class ClassB : ClassA
{
public ClassB(dynamic test)
: base(test)
{
Console.WriteLine("ClassB");
}
}
It works if I cast the argument to object, like this:
public ClassB(dynamic test)
: base((object)test)
So, I'm a little confused. Why do I have to put this nasty cast in - why can't the compiler figure out what I mean?
The constructor chain has to be determined for certain at compile-time - the compiler has to pick an overload so that it can create valid IL. Whereas normally overload resolution (e.g. for method calls) can be deferred until execution time, that doesn't work for chained constructor calls.
EDIT: In "normal" C# code (before C# 4, basically), all overload resolution is performed at compile-time. However, when a member invocation involves a dynamic value, that is resolved at execution time. For example consider this:
using System;
class Program
{
static void Foo(int x)
{
Console.WriteLine("int!");
}
static void Foo(string x)
{
Console.WriteLine("string!");
}
static void Main(string[] args)
{
dynamic d = 10;
Foo(d);
}
}
The compiler doesn't emit a direct call to Foo here - it can't, because in the call Foo(d) it doesn't know which overload it would resolve to. Instead it emits code which does a sort of "just in time" mini-compilation to resolve the overload with the actual type of the value of d at execution time.
Now that doesn't work for constructor chaining, as valid IL has to contain a call to a specific base class constructor. (I don't know whether the dynamic version can't even be expressed in IL, or whether it can, but the result would be unverifiable.)
You could argue that the C# compiler should be able to tell that there's only actually one visible constructor which can be called, and that constructor will always be available... but once you start down that road, you end up with a language which is very complicated to specify. The C# designers usually take the position of having simpler rules which occasionally aren't as powerful as you'd like them to be.
Method overloading allows us to define many methods with the same name but with a different set of parameters ( thus with the same name but different signature ).
Are these two methods overloaded?
class A
{
public static void MyMethod<T>(T myVal) { }
public static void MyMethod(int myVal) { }
}
EDIT:
Shouldn't statement A<int>.MyMethod(myInt); throw an error, since constructed type A<int> has two methods with the same name and same signature?
Are the two methods overloaded?
Yes.
Shouldn't statement A<int>.MyMethod(myInt); throw an error, since constructed type A<int> has two methods with the same signature?
The question doesn't make sense; A is not a generic type as you have declared it. Perhaps you meant to ask:
Should the statement A.MyMethod(myInt); cause the compiler to report an error, since there are two ambiguous candidate methods?
No. As others have said, overload resolution prefers the non-generic version in this case. See below for more details.
Or perhaps you meant to ask:
Should the declaration of type A be illegal in the first place, since in some sense it has two methods with the same signature, MyMethod and MyMethod<int>?
No. The type A is perfectly legal. The generic arity is part of the signature. So there are not two methods with the same signature because the first has generic arity zero, the second has generic arity one.
Or perhaps you meant to ask:
class G<T>
{
public static void M(T t) {}
public static void M(int t) {}
}
Generic type G<T> can be constructed such that it has two methods with the same signature. Is it legal to declare such a type?
Yes, it is legal to declare such a type. It is usually a bad idea, but it is legal.
You might then retort:
But my copy of the C# 2.0 specification as published by Addison-Wesley states on page 479 "Two function members declared with the same names ... must have have parameter types such that no closed constructed type could have two members with the same name and signature." What's up with that?
When C# 2.0 was originally designed that was the plan. However, then the designers realized that this desirable pattern would be made illegal:
class C<T>
{
public C(T t) { ... } // Create a C<T> from a given T
public C(Stream s) { ... } // Deserialize a C<T> from disk
}
And now we say sorry buddy, because you could say C<Stream>, causing two constructors to unify, the whole class is illegal. That would be unfortunate. Obviously it is unlikely that anyone will ever construct this thing with Stream as the type parameter!
Unfortunately, the spec went to press before the text was updated to the final version. The rule on page 479 is not what we implemented.
Continuing to pose some more questions on your behalf:
So what happens if you call G<int>.M(123) or, in the original example, if you call A.MyMethod(123)?
When overload resolution is faced with two methods that have identical signatures due to generic construction then the one that is generic construction is considered to be "less specific" than the one that is "natural". A less specific method loses to a more specific method.
So why is it a bad idea, if overload resolution works?
The situation with A.MyMethod isn't too bad; it is usually pretty easy to unambiguously work out which method is intended. But the situation with G<int>.M(123) is far worse. The CLR rules make this sort of situation "implementation defined behaviour" and therefore any old thing can happen. Technically, the CLR could refuse to verify a program that constructs type G<int>. Or it could crash. In point of fact it does neither; it does the best it can with the bad situation.
Are there any examples of this sort of type construction causing truly implementation-defined behaviour?
Yes. See these articles for details:
https://ericlippert.com/2006/04/05/odious-ambiguous-overloads-part-one/
https://ericlippert.com/2006/04/06/odious-ambiguous-overloads-part-two/
Yes. MyMethod(int myVal) will be called when the type of the parameter is an int, the generic overload will be called for all other parameter arguments, even when the parameter argument is implicitly convertible to (or is a derived class of) the hardcoded type. Overload resolution will go for the best fit, and the generic overload will resolve to an exact match at compile time.
Note: You can explicitly invoke the generic overload and use an int by providing the type parameter in the method call, as Steven Sudit points out in his answer.
short s = 1;
int i = s;
MyMethod(s); // Generic
MyMethod(i); // int
MyMethod((int)s); // int
MyMethod(1); // int
MyMethod<int>(1); // Generic**
MyMethod(1.0); // Generic
// etc.
Yes, they are. They will allow code as such:
A.MyMethod("a string"); // calls the generic version
A.MyMethod(42); // calls the int version
Yes, they are overloaded. The compiler is supposed to prefer explicit method signatures against generic methods if they are available. Beware, however, that if you can avoid this kind of overload you probably should. There have been bug reports with respect to this sort of overload and unexpected behaviors.
https://connect.microsoft.com/VisualStudio/feedback/details/522202/c-3-0-generic-overload-call-resolution-from-within-generic-function
Yes. They have the same name "MyMethod" but different signatures. The C# specification, however, specifically handles this by saying that the compiler will prefer the non-generic version over the generic version, when both are options.
Yes. Off the top of my head, if you call A.MyMethod(1);, it will always run the second method. You'd have to call A.MyMethod<int>(1); to force it to run the first.
In Scala, I can define structural types as follows:
type Pressable = { def press(): Unit }
This means that I can define a function or method which takes as an argument something that is Pressable, like this:
def foo(i: Pressable) { // etc.
The object which I pass to this function must have defined for it a method called press() that matches the type signature defined in the type - takes no arguments, returns Unit (Scala's version of void).
I can even use the structural type inline:
def foo(i: { def press(): Unit }) { // etc.
It basically allows the programmer to have all the benefits of duck typing while still having the benefit of compile-time type checking.
Does C# have something similar? I've Googled but can't find anything, but I'm not familiar with C# in any depth. If there aren't, are there any plans to add this?
No, and no plans that I know of. Only named (rather than structural) subtyping (e.g. interfaces).
(Others may want to see also
http://en.wikipedia.org/wiki/Nominative_type_system
http://en.wikipedia.org/wiki/Structural_type_system
)
(A few people may point out some exotic corner cases, like the foreach statement using structural typing for GetEnumerator, but this is the exception rather than the rule.)
There isn't a way to define structural types that has a particular function. There is a library that adds duck typing support to C# that can be found here.
This is the example from Duck Typing project. Please note the the duck typing happens at runtime and can fail. It is my understanding also that this library generates proxies for the types that are duck typed, which is far cry from the elegant compile-time support that is enjoyed in Scala. This is most likely as good as it gets with this generation of C#.
public interface ICanAdd
{
int Add(int x, int y);
}
// Note that MyAdder does NOT implement ICanAdd,
// but it does define an Add method like the one in ICanAdd:
public class MyAdder
{
public int Add(int x, int y)
{
return x + y;
}
}
public class Program
{
void Main()
{
MyAdder myAdder = new MyAdder();
// Even though ICanAdd is not implemented by MyAdder,
// we can duck cast it because it implements all the members:
ICanAdd adder = DuckTyping.Cast<ICanAdd>(myAdder);
// Now we can call adder as you would any ICanAdd object.
// Transparently, this call is being forwarded to myAdder.
int sum = adder.Add(2, 2);
}
}
This is the C# way of achieving the same thing using the good ol boring interfaces.
interface IPressable {
void Press();
}
class Foo {
void Bar(IPressable pressable) {
pressable.Press();
}
}
class Thingy : IPressable, IPushable, etc {
public void Press() {
}
}
static class Program {
public static void Main() {
pressable = new Thingy();
new Foo().Bar(pressable);
}
}
As others noted, this is not really available in .NET (as this is more a matter of the runtime than a language). However, .NET 4.0 supports similar thing for imported COM interfaces and I believe this could be used for implementing structural typing for .NET. See this blog post:
Faking COM to fool the C# compiler
I didn't try playing with this myself yet, but I think it might enable compiler authors to write languages with structural typing for .NET. (The idea is that you (or a compiler) would define an interface behind the scene, but it would work, because the interfaces would be treated as equivalent thanks to the COM equivalence feature).
Also, C# 4.0 supports the dynamic keyword which, I think, could be interpreted as a structural typing (with no static type checking). The keyword allows you to call methods on any object without knowning (at compile-time) whether the object will have the required methods. This is essentially the same thing as the "Duck typing" project mentioned by Igor (but that's, of course, not a proper structural typing).
The awaitable pattern in C# can perhaps be interpreted as a limited, ad hoc instance of structural subtyping / existential typing. The compiler will only await objects that have access to a GetAwaiter() method that returns any INotifyCompletion object with a specific set of methods and properties. Since neither the 'awaitable' object nor the 'awaiter' object needs to implement any interface (except INotifyCompletion in the case of the latter), await is similar to a method that accepts structurally typed awaitable objects.