Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic methods and method overloading

Tags:

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?

like image 730
user437291 Avatar asked Sep 09 '10 18:09

user437291


People also ask

What are generic methods?

Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.

How can generic methods be overloaded develop a code with example?

A generic method can also be overloaded by non-generic methods that have the same method name and number of parameters. When the compiler encounters a method call, it searches for the method declaration that most precisely matches the method name and the argument types specified in the call.

What is method overloading?

Method overloading is a form of polymorphism in OOP. Polymorphism allows objects or methods to act in different ways, according to the means in which they are used. One such manner in which the methods behave according to their argument types and number of arguments is method overloading.

Can we override generic method in C#?

Similar to John Carpenter's answer, you can override the generic method with the same generic method, but simply use the as operator to check and cast it to the desired type. This has the added benefit of using null-testing to check if the conversion worked.


2 Answers

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/

like image 87
Eric Lippert Avatar answered Sep 17 '22 21:09

Eric Lippert


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. 
like image 25
Anthony Pegram Avatar answered Sep 17 '22 21:09

Anthony Pegram