class foo
{
public void bar(int i) { ... };
public void bar(long i) { ... };
}
foo.bar(10);
I would expect this code to give me some error, or at least an warning, but not so...
What version of bar() is called, and why?
The int version of bar is being called, because 10 is an int literal and the compiler will look for the method which closest matches the input variable(s). To call the long version, you'll need to specify a long literal like so: foo.bar(10L);
Here is a post by Eric Lippert on much more complicated versions of method overloading. I'd try and explain it, but he does a much better job and I ever could: http://blogs.msdn.com/b/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx
from the C# 4.0 Specification:
Method overloading permits multiple
methods in the same class to have the
same name as long as they have unique
signatures. When compiling an
invocation of an overloaded method,
the compiler uses overload resolution
to determine the specific method to
invoke. Overload resolution finds the
one method that best matches the
arguments or reports an error if no
single best match can be found. The
following example shows overload
resolution in effect. The comment for
each invocation in the Main method
shows which method is actually
invoked.
class Test {
static void F() {
Console.WriteLine("F()");
}
static void F(object x) {
Console.WriteLine("F(object)");
}
static void F(int x) {
Console.WriteLine("F(int)");
}
static void F(double x) {
Console.WriteLine("F(double)");
}
static void F<T>(T x) {
Console.WriteLine("F<T>(T)");
}
static void F(double x, double y) {
Console.WriteLine("F(double,double)");
}
static void Main() {
F(); // Invokes F()
F(1); // Invokes F(int)
F(1.0); // Invokes F(double)
F("abc"); // Invokes F(object)
F((double)1); // Invokes F(double)
F((object)1); // Invokes F(object)
F<int>(1); // Invokes F<T>(T)
F(1, 1); // Invokes F(double, double)
}
}
As shown by the example, a particular
method can always be selected by
explicitly casting the arguments to
the exact parameter types and/or
explicitly supplying type arguments.
As Kevin says, there's an overload resolution process in place. The basic sketch of the process is:
Identify all the accessible candidate methods, possibly using type inference on generic methods
Filter out the inapplicable methods; that is, the methods that cannot work because the arguments don't convert implicitly to the parameter types.
Once we have a set of applicable candidates, run more filters on them to determine the unique best one.
The filters are pretty complicated. For example, a method originally declared in a more derived type is always better than a method originally declared in a less derived type. A method where the argument types exactly match the parameter types is better than one where there are inexact matches. And so on. See the specification for the exact rules.
In your particular example the "betterness" algorithm is straightforward. The exact match of int to int is better than the inexact match of int to long.
I would say if you exceed below limit
-2,147,483,648 to 2,147,483,647
control will go to long
Range for long
–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
Max value for int
foo.bar(-2147483648);
or
foo.bar(2147483648);
Long will get control if we exceed the value by 2147483648
Related
namespace test
{
class Program
{
static void Main(string[] args)
{
Derived obj = new Derived();
int i = 10;
obj.Foo(i);
Console.ReadLine();
}
}
class Base
{
public virtual void Foo(int i)
{
Console.WriteLine("Base:Foo()");
}
}
class Derived:Base
{
public override void Foo(int i)
{
Console.WriteLine("Foo(int)");
}
public void Foo(object i)
{
Console.WriteLine("Foo(object)");
}
}
}
output of the program according to me should be Foo(int) but output is coming as Foo(object) please help me in understanding the diffrence in output
Good question, I can reproduce your results. If one takes a look at the C# specifications one will find the following snippets:
7.5.3 Overload resolution
For example, the set of candidates for a method invocation does not
include methods marked override (§7.4), and methods in a base class
are not candidates if any method in a derived class is applicable
(§7.6.5.1).
7.4 Member Lookup
Otherwise, the set consists of all accessible (§3.5) members named N
in T, including inherited members and the accessible members named N
in object. If T is a constructed type, the set of members is obtained
by substituting type arguments as described in §10.3.2. Members that
include an override modifier are excluded from the set.
7.6.5.1 Method invocations
The set of candidate methods is reduced to contain only methods from
the most derived types: For each method C.F in the set, where C is the
type in which the method F is declared, all methods declared in a base
type of C are removed from the set. Furthermore, if C is a class type
other than object, all methods declared in an interface type are
removed from the set.
Sounds a bit complicated? Even the C# designers seem to think so and put in the 'helpful' note:
7.6.5.1 Method invocations
The intuitive effect of the resolution rules described above is as
follows: To locate the particular method invoked by a method
invocation, start with the type indicated by the method invocation and
proceed up the inheritance chain until at least one applicable,
accessible, non-override method declaration is found. Then perform
type inference and overload resolution on the set of applicable,
accessible, non-override methods declared in that type and invoke the
method thus selected. If no method was found, try instead to process
the invocation as an extension method invocation.
If we take a look at your derived class, we see two possible methods for C# to use:
A) public override void Foo(int i)
B) public void Foo(object i)
Let's use that last checklist!
Applicability - Both A and B are applicable -(both are void, both are named 'Foo' and both can accept an integer value).
Accessibility - Both A and B are accessible (public)
Not Overridden - Only B is not overridden.
But wait you might say! A is more specific than B!
Correct, but that consideration is only made after we've disregarded option A. As Eric Lippert (one of the designers) puts it Closer is always better than farther away. (Thanks Anthony Pegram)
Addendum
There is always the 'new' keyword:
class Derived : Base
{
public new void Foo(int i)
{
Console.WriteLine("Foo(int)");
}
public void Foo(object i)
{
Console.WriteLine("Foo(object)");
}
}
Though the specifics of that best left for another question!
The simple datatype int descends from object. You are overriding the function and also overloading the parameter list. Since the function name is the same with a different signature the compiler allows this. For simple objects, I image one copy of the parameter signature in the most basic form is stored in the method table.
I have a class that overrides the addition operator twice. One that takes the type parameter and one that takes a double:
public class A<T>
{
public A() { }
public static A<T> operator +(A<T> a, T t)
{
Console.WriteLine("Generic add called.");
return new A<T>(); // return to keep the compiler happy
}
public static A<T> operator +(A<T> a, double d)
{
Console.WriteLine("Double add called.");
return new A<T>(); // return to keep the compiler happy
}
}
When the class is parameterized by the int type, it behaves as expected:
A<int> aInt = new A<int>();
var test = aInt + 3;
// -> Generic add called.
test = aInt + 3.0;
// -> Double add called.
But when parameterized by the double type, the non-generic add is called:
A<double> aDouble = new A<double>();
var otherTest = aDouble + 3.0;
// -> Double add called.
Assuming this behavior is the norm, I know which will be called. The non-generic override will be preferred. That said...
Will the non-generic method be always be preferred in the event of a collision?
All of the above code is available, runnable in your browser, here
EDIT: This question is related, but it's asking about generic methods, not classes. He gives this code:
class A
{
public static void MyMethod<T>(T myVal) { }
public static void MyMethod(int myVal) { }
}
which does not apply to my usage examples. Distinguishing between a.MyMethod(3) and a.MyMethod<int>(3) is obvious - one is generic and one is not.
The more specific method will be chosen, but that construction is a bad idea because it is technically unspecified behaviour.
To quote #EricLippert, substituting the code snippets for the ones from my question:
But the situation with [aDouble + 3.0] 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 [A<double>]. 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:
http://blogs.msdn.com/b/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx
http://blogs.msdn.com/b/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx
Simple answering yes. The compiler assume that because you have treated by hand a particular type parameter, that means that it has some special logic for you. That's why the second operator is called. To say further, operators are nothing more than static methods that accepts some parameters. For your case it's a binary operator so the static method has two parameters.
The new Task.Run static method that's part of .NET 4.5 doesn't seem to behave as one might expect.
For example:
Task<Int32> t = Task.Run(()=>5);
compiles fine, but
Task<Int32> t = Task.Run(MyIntReturningMethod);
...
public Int32 MyIntReturningMethod() {
return (5);
}
complains that MyIntReturningMethod is returning the wrong type.
Perhaps I am just not understanding which overload of Task.Run is being called. But in my mind, my lambda code above looks a lot like a Func<Int32>, and MyIntReturningMethod is definitely compatible with Func<Int32>
Any ideas of what's going on?
Michael
(Of course, to get out of the problem, simply say Task.Run((Func<int>)MyIntReturningMethod).)
This has absolutely nothing to do with Task and so on.
One problem to be aware of here is that when very many overloads are present, the compiler error text will focus on just one "pair" of overloads. So that is confusing. The reason is that the algorithm to determine the best overload considers all overloads, and when that algorithm concludes that no best overload can be found, that does not produce a certain pair of overloads for the error text because all overloads may (or may not) have been involved.
To understand what happens, see instead this simplified version:
static class Program
{
static void Main()
{
Run(() => 5); // compiles, goes to generic overload
Run(M); // won't compile!
}
static void Run(Action a)
{
}
static void Run<T>(Func<T> f)
{
}
static int M()
{
return 5;
}
}
As we see, this has absolutely no reference to Task, but still produces the same problem.
Note that anonymous function conversions and method group conversions are (still) not the exact same thing. Details are to be found in the C# Language Specification.
The lambda:
() => 5
is actually not even convertible to the System.Action type. If you try to do:
Action myLittleVariable = () => 5;
it will fail with error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement. So it is really clear which overload to use with the lambda.
On the other hand, the method group:
M
is convertible to both Func<int> and Action. Remember that it is perfectly allowed to not pick up a return value, just like the statement:
M(); // don't use return value
is valid by itself.
This sort-of answers the question but I will give an extra example to make an additional point. Consider the example:
static class Program
{
static void Main()
{
Run(() => int.Parse("5")); // compiles!
}
static void Run(Action a)
{
}
static void Run<T>(Func<T> f)
{
}
}
In this last example, the lambda is actually convertible to both delegate types! (Just try to remove the generic overload.) For the right-hand-side of the lambda arrow => is an expression:
int.Parse("5")
which is valid as a statement by itself. But overload resolution can still find a better overload in this case. As I said earlier, check the C# Spec.
Inspired by HansPassant and BlueRaja-DannyPflughoeft, here is one final (I think) example:
class Program
{
static void Main()
{
Run(M); // won't compile!
}
static void Run(Func<int> f)
{
}
static void Run(Func<FileStream> f)
{
}
static int M()
{
return 5;
}
}
Note that in this case, there is absolutely no way the int 5 could be converted into a System.IO.FileStream. Still the method group conversion fails. This might be related to the fact the with two ordinary methods int f(); and FileStream f();, for example inherited by some interface from two different base interfaces, there is no way to resolve the call f();. The return type is not part of a method's signature in C#.
I still avoid to introduce Task in my answer since it could give a wrong impression of what this problem is about. People have a hard time understanding Task, and it is relatively new in the BCL.
This answer has evolved a lot. In the end, it turns out that this is really the same underlying problem as in the thread Why is Func<T> ambiguous with Func<IEnumerable<T>>?. My example with Func<int> and Func<FileStream> is almost as clear. Eric Lippert gives a good answer in that other thread.
This was supposed to be fixed in .Net 4.0, but Task.Run() is new to .Net 4.5
.NET 4.5 has its own overload ambiguity by adding the Task.Run(Func<Task<T>>) method. And the support for async/await in C# version 5. Which permits an implicit conversion from T foo() to Func<Task<T>>.
That's syntax sugar that's pretty sweet for async/await but produces cavities here. The omission of the async keyword on the method declaration is not considered in the method overload selection, that opens another pandora box of misery with programmers forgetting to use async when they meant to. Otherwise follows the usual C# convention that only the method name and arguments in the method signature is considered for method overload selection.
Using the delegate type explicitly is required to resolve the ambiguity.
When you pass a Func<TResult> into a method Run<TResult>(Func<TResult>) you don't have to specify the generic on the methodcall because it can infer it. Your lambda does that inference.
However, your function is not actually a Func<TResult> whereas the lambda was.
If you do Func<Int32> f = MyIntReturningMethod it works. Now if you specify Task.Run<Int32>(MyIntReturningMethod) you would expect it to work also. However it can't decide if it should resolve the Func<Task<TResult>> overload or the Func<TResult> overload, and that doesn't make much sense because its obvious that the method is not returning a task.
If you compile something simple like follows:
void Main()
{
Thing(MyIntReturningMethod);
}
public void Thing<T>(Func<T> o)
{
o();
}
public Int32 MyIntReturningMethod()
{
return (5);
}
the IL looks like this....
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: ldftn UserQuery.MyIntReturningMethod
IL_0009: newobj System.Func<System.Int32>..ctor
IL_000E: call UserQuery.Thing
(Some of the extra stuff is from LINQ Pad's additions... like the UserQuery part)
The IL looks identical as if you do an explicit cast. So it seems like the compiler does't actually know which method to use. So it doesn't know what cast to create automatically.
You can just use Task.Run<Int32>((Func<Int32>)MyIntReturningMethod) to help it out a bit. Though I do agree that this seems like something the compiler should be able to handle. Because Func<Task<Int32>> is not the same as Func<Int32>, so it doesn't make sense that they would confuse the compiler.
Seems like an overload resolution problem. The compiler can't tell which overload you're calling (because first it has to find the correct delegate to create, which it doesn't know because that depends on the overload you're calling). It would have to guess-and-check but I'm guessing it's not that smart.
The approach of Tyler Jensen works for me.
Also, you can try this using a lambda expression:
public class MyTest
{
public void RunTest()
{
Task<Int32> t = Task.Run<Int32>(() => MyIntReturningMethod());
t.Wait();
Console.WriteLine(t.Result);
}
public int MyIntReturningMethod()
{
return (5);
}
}
Here's my stab at it:
public class MyTest
{
public void RunTest()
{
Task<Int32> t = Task.Run<Int32>(new Func<int>(MyIntReturningMethod));
t.Wait();
Console.WriteLine(t.Result);
}
public int MyIntReturningMethod()
{
return (5);
}
}
I have the following simple code
abstract class A
{
public abstract void Test(Int32 value);
}
class B : A
{
public override void Test(Int32 value)
{
Console.WriteLine("Int32");
}
public void Test(Double value)
{
Test((Int32)1);
}
}
When I ran this code the line Test((Int32)1) causes stack overflow due to infinite recursion. The only possible way to correctly call proper method (with integer parameter) I found is
(this as A).Test(1);
But this is not appropriate for me, because both methods Test are public and I am willing the users to be able to call both method?
Method overload resolution in C# does not always behave as you might expect, but your code is behaving according to the specification (I wrote a blog post about this a while ago).
In short, the compiler start off by finding methods that
Has the same name (in your case Test)
are declared in the type (in your case B) or one of its base types
are not declared with the override modifier
Note that last point. This is actually logical, since virtual methods are resolved in run-time, not compile time.
Finally, if the type (in this case B) has a method that is a candidate (which means that the parameters in your call can be implicitly converted to the parameter type of the candidate method), that method will be used. Your overridden method is not even part of the decision process.
If you want to call your overridden method, you will need to cast the object to its base type first.
Unfortunately in order to call the A::Test(int) through a B reference some sort of cast is needed. So long as the C# compiler sees the reference through B it will pick the B::Test(double) version.
A slightly less ugly version is the following
((A)this).Test(1);
Another thought though is have a private method with a different name that both feed into.
class B : A {
public override void Test(int i) {
TestCore(i);
}
public void Test(double d) {
TestCore(1);
}
private void TestCore(int i) {
// Combined logic here
}
}
A delegate is a function pointer. So it points to a function which meets the criteria (parameters and return type).
This begs the question (for me, anyway), what function will the delegate point to if there is more than one method with exactly the same return type and parameter types? Is the function which appears first in the class?
Thanks
The exact method is specified when you create the Delegate.
public delegate void MyDelegate();
private void Delegate_Handler() { }
void Init() {
MyDelegate x = new MyDelegate(this.Delegate_Handler);
}
As Henk says, the method is specified when you create the delegate. Now, it's possible for more than one method to meet the requirements, for two reasons:
Delegates are variant, e.g. you can use a method with an Object parameter to create an Action<string>
You can overload methods by making them generic, e.g.
static void Foo() {}
static void Foo<T>(){}
static void Foo<T1, T2>(){}
The rules get quite complicated, but they're laid down in section 6.6 of the C# 3.0 spec. Note that inheritance makes things tricky too.
So it points to a function which meets the criteria (parameters and return type).
Nope.
To add some background to Henk's Answer:
Just like int x is an variable which can contain integers, A delegate is a variable which can contain functions.
It points to whatever function you tell it to point to.
EG:
// declare the type of the function that we want to point to
public delegate void CallbackHandler(string); //
...
// declare the actual function
public void ActualCallbackFunction(string s){ ... }
...
// create the 'pointer' and assign it
CallbackHandler functionPointer = ActualCallbackFunction;
// the functionPointer variable is now pointing to ActualCallbackFunction