Overloading and method signatures.

  • Thread starter Marcos Stefanakopolus
  • Start date
M

Marcos Stefanakopolus

So this is ok:

class foo {
int myMethod(string, int) { ... }
int myMethod(string, double) { ... }
}

But this is not:

class foo {
int myMethod(string) { ... }
double myMethod(string) { ... }
}

The compiler complains "Class 'foo' already defines a member called
'myMethod' with the same parameter types'. Well, yes that's true, but my
question is "why on earth is the return type not considered part of a
method's signature for purposes of overload disambiguation?"

Can someone with perhaps a deeper understanding of C# clue me in as to why
this is the case? When calling the method in contexts such as:

int I = myMethod("Bob");
double D = myMethod("Sue");

There's no ambiguity about which implementation is meant. In contexts such
as:

Decimal Num = 1.0 + myMethod("Dave") + 7;

The compiler could simply require a cast to disambiguiate which type is
intended. The C# compiler doesn't seem to have any problem requiring silly
casts in all sorts of other places, so why would it be so bad to require
this:

Decimal Num = 1.0 + (double)myMethod("Dave") + 7;

Perhaps I'm just irritated that C# is making my job more difficult at the
moment because return type is _not_ part of a method's signature, but I'd
like to understand why and hear any suggestions as to ways to handle
situations where you do want to have two methods with the same name that
differ only in return type.
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

very simple:

object o = foo_instance.myMethod( "which one to call?")

Now imagine the complexity when you return a reference type , this why you
need to differentiate in parameters and the return is not considered

cheers,
 
A

Ajay Kalra

So you could say that problem is because the compiler will get confused
as it is being *helpful* and wants to do the implicit conversion.

I guess this is a choice made in designing the language. If it was
chosen to flag this as a compile time error, you would be able to have
method overloading w/same parameters but with different return type.
IIRC, this is how C++ behaves as well.
 
B

Bruce Wood

The simple answer is because of precisely the example you gave: there
are many situations in which the compiler can't determine which one to
call.

The more complex answer involves looking at the solution you proposed,
and seeing it from the compiler's point of view. You suggested this bit
of code to disambiguate the situation:

class foo {
int myMethod(string) { ... }
double myMethod(string) { ... }
}

Decimal Num = 1.0 + (double)myMethod("Dave") + 7;

where the cast to (double) tells the compiler which method to call.
However, compilers don't see things that way.

As soon as you evaluate 'myMethod("Dave")', it becomes a value to be
used in a calculation. The compiler doesn't "look ahead," as such, to
see what kind of value it's going to need in the expression, or to what
kind of value this value is going to be cast. That's all "in the
future" as it were.

This isn't unique to C#, by the way. I know of no language that allows
overloads that will distinguish between two methods based on their
return values alone. In particular, C++ and Java, which provided
inspiration for C#, don't allow it, either.
 
J

Jon Skeet [C# MVP]

Bruce Wood said:
This isn't unique to C#, by the way. I know of no language that allows
overloads that will distinguish between two methods based on their
return values alone. In particular, C++ and Java, which provided
inspiration for C#, don't allow it, either.

IL itself does, interestingly enough. The method calls specify the
return type of the called method.

The CTS allows it, but the CLS doesn't - in other words, any class
which has two methods defined which differ only by return type doesn't
have to be consumed by a CLS-compliant language.
 
P

probashi

We need to add class name or instance ref in this code
Decimal Num = 1.0 + (double)myMethod("Dave") + 7;

Foo f = new Foo();

Decimal Num = 1.0 + (double) f.myMethod("Dave") + 7;

now the cast to double is invalid!!
 
R

Raaj

The compiler complains "Class 'foo' already defines a member called
'myMethod' with the same parameter types'. Well, yes that's true, but my
question is "why on earth is the return type not considered part of a
method's signature for purposes of overload disambiguation?"
This is because, the compiler (any compiler i know of) doesnt force you
either to assign the return value that a method or function returns to
appropriate type.

wrt. the example oulined by you, i can do away as follows:

private void CallFoo()
{
myMethod('foo');
}

The callFoo() is really not concerned about the return value of
myMethod but is only making the call to myMethod(), there is no basis
here for the compiler to figure out at run time as to which version of
myMethod() is called.

Thanks,

Raaj, Umapathy.
 
M

Marcos Stefanakopolus

Thanks to everyone who replied. After thinking about it, I realized that
some part of my brain has been spoiled by Perl. Perl provides an expression
context when evaluating expressions, so that code can check whether it's
supposed to return a number or a string or a list or whatever, and then do
the right thing. C# acts in a vaguely similar way when it lets you say
things like:

int theNumber = 7;
Console.WriteLine("the number is " + theNumber);

Knowing that the expression is in "string context", the compiler calls
ToString on theNumber for you. Nice feature, but it led me to thinking that
knowledge of the calling context was something that the compiler would take
into account in a more general way. Sadly, not the case.

I'll post a separate thread to discuss possible work-arounds.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top