By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,719 Members | 1,875 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,719 IT Pros & Developers. It's quick & easy.

Why can't overloads take into account the return type.

P: n/a
eg

void DoIt()
{
int i = FromString("1");
double d = FromString("1.1");
}

int FromString(string SomeValue)
{
return int.Parse(SomeValue);
}

double FromString(string SomeValue)
{
return double.Parse(SomeValue);
}

The return type is really just a byref param underneath anyway I presume.
Nov 17 '05 #1
Share this Question
Share on Google+
59 Replies


P: n/a
mdb
"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in
news:#j**************@TK2MSFTNGP09.phx.gbl:
eg

void DoIt()
{
int i = FromString("1");
double d = FromString("1.1");
}

int FromString(string SomeValue)
{
return int.Parse(SomeValue);
}

double FromString(string SomeValue)
{
return double.Parse(SomeValue);
}

The return type is really just a byref param underneath anyway I
presume.


Because the function call and assigning the result are two completely
different things. You don't even have to assign the result. So, tell
me... For example, what would happen if I did these:

// This doesn't get assigned anywhere - which one should I call?
FromString("3.14159");

// What should this return - a double or an int?
int i = (int)FromString("3.14159");

// Or even worse...
double d = (int)FromString("3.14159");

I'm sure you can see how ridiculous this would get if it did consider
return type...

-mdb
Nov 17 '05 #2

P: n/a
"mdb" <m_b_r_a_y@c_t_i_u_s_a__d0t__com> wrote in message
news:Xn****************************@207.46.248.16. ..
Because the function call and assigning the result are two completely
different things.
In VB6 the return value was just another parameter under the hood. The
actual return value was the error code, which I presume is the same in C#.
Someone correct me if i'm wrong.
You don't even have to assign the result. So, tell
me... For example, what would happen if I did these:
In any of those cases it would give an error in exactly the same way as it
would if it couldn't resolve an overload. See code below.
I'm sure you can see how ridiculous this would get if it did consider
return type...


Not at all. In this case the developer has chosen to have the return type
part of the signature by creating 2 overloads with the only difference being
the return type. Because it can be turned on and off I can't see any problem
with it.

Michael

[STAThread]
static void Main()
{
DoIt(null);
}

static void DoIt(Class1 SomeValue)
{
}

static void DoIt(Class2 SomeValue)
{
}
Nov 17 '05 #3

P: n/a

"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:ex**************@TK2MSFTNGP14.phx.gbl...
"mdb" <m_b_r_a_y@c_t_i_u_s_a__d0t__com> wrote in message
news:Xn****************************@207.46.248.16. ..
Because the function call and assigning the result are two completely
different things.


In VB6 the return value was just another parameter under the hood. The
actual return value was the error code, which I presume is the same in C#.
Someone correct me if i'm wrong.


Sorry, you're wrong about C#.
Nov 17 '05 #4

P: n/a
"Mike Schilling" <ms*************@hotmail.com> wrote in message
news:er**************@TK2MSFTNGP10.phx.gbl...
In VB6 the return value was just another parameter under the hood. The
actual return value was the error code, which I presume is the same in
C#. Someone correct me if i'm wrong.


Sorry, you're wrong about C#.


Fair enough although it's probably not relevant anyway (I know *I* brought
it up :-)

Michael
Nov 17 '05 #5

P: n/a
"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:ex**************@TK2MSFTNGP14.phx.gbl...
"mdb" <m_b_r_a_y@c_t_i_u_s_a__d0t__com> wrote in message
news:Xn****************************@207.46.248.16. ..
In VB6 the return value was just another parameter under the hood. The
actual return value was the error code, which I presume is the same in C#.
Someone correct me if i'm wrong.


I think you are confusing VB6 with COM. It is true that the COM Invoke()
function always returns an HRESULT, with the actual function return value
being an out parameter of Invoke(). However, I don't believe that is true
of the core language implementation. And anyway, neither VB nor COM allow
function overloading.

The answer to your original question about return values not being taken
into account in function overloads has to do with ambiguity. If you had two
functions by the same name that differed only by return type, say

int Foo() {return 3;}
string Foo() {return "xyz";}

What would the compiler assign to x?

object x = Foo() + Foo();

-- Alan
Nov 17 '05 #6

P: n/a
"Alan Pretre" <al********@newsgroup.nospam> wrote in message
news:Ou**************@tk2msftngp13.phx.gbl...
I think you are confusing VB6 with COM. It is true that the COM Invoke()
function always returns an HRESULT, with the actual function return value
being an out parameter of Invoke(). However, I don't believe that is true
of the core language implementation. And anyway, neither VB nor COM allow
function overloading.
VB6 uses the HRESULT method throughout except for code in modules, which is
why a module is the only place you can put an API callback.
The answer to your original question about return values not being taken
into account in function overloads has to do with ambiguity. If you had
two functions by the same name that differed only by return type, say

int Foo() {return 3;}
string Foo() {return "xyz";}

What would the compiler assign to x?

object x = Foo() + Foo();


But why is that such a problem? In the cases where the programmer decided to
use this it is just something they would have to take into account. They
have to take it into account now with parameters of the function, it's not
really any different. If it was only used where appropriate it would be
quite effective, eg

int i = Parse("123");
double d = Parse(123.45");

what you are saying is that it can be misused therefore it should not be
implemented but every feature can be misued.

Michael
Nov 17 '05 #7

P: n/a
"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...
"Alan Pretre" <al********@newsgroup.nospam> wrote in message
news:Ou**************@tk2msftngp13.phx.gbl...
what you are saying is that it can be misused therefore it should not be
implemented but every feature can be misued.


When you add implicit type conversions to the mix, then besides the
technical problems there would be for code generation, there would be many
opportunities for subtle bugs.

-- Alan
Nov 17 '05 #8

P: n/a
Alan Pretre wrote:
"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...
"Alan Pretre" <al********@newsgroup.nospam> wrote in message
news:Ou**************@tk2msftngp13.phx.gbl...
what you are saying is that it can be misused therefore it should not be
implemented but every feature can be misued.

When you add implicit type conversions to the mix, then besides the
technical problems there would be for code generation, there would be many
opportunities for subtle bugs.

No implicit type conversions there (I think).
What Michael is saying is that there would be a
double Parse(string value)
int Parse(string value)

Therefore since you are assigning to a double, the return type of double
method would be used.

etc..

If you use implicit casting say from int to double then you could maybe
run into trouble.

I think
JB
-- Alan

Nov 17 '05 #9

P: n/a
John B wrote:
What Michael is saying is that there would be a
double Parse(string value)
int Parse(string value)
Therefore since you are assigning to a double, the return type of
double method would be used.


Ok. Now, let's pretend that we also have some overloaded methods that take
different argument types, say:

void Print(int i)
void Print(double i)

Now, someone comes along and writes:

int x = 5;

Print( x * Parse(something) );

Besides not having any clue which Print() and which Parse() to use, the
compiler doesn't even have a clue whether to use integer or floating point
multiplication.

The other problem with this is that it most definitely doesn't encourage
good object oriented design.

--
Chris Priede (pr****@panix.com)
Nov 17 '05 #10

P: n/a
This issue has been discussed before. For a very long discussion, see for
example:

http://tinyurl.com/b8och

There are others. Google the C# newsgroup for more.

-- Alan
Nov 17 '05 #11

P: n/a
"Chris Priede" <pr****@panix.com> wrote in message
news:OG******************@TK2MSFTNGP14.phx.gbl...
Ok. Now, let's pretend that we also have some overloaded methods that
take different argument types, say:

void Print(int i)
void Print(double i)

Now, someone comes along and writes:

int x = 5;

Print( x * Parse(something) );

Besides not having any clue which Print() and which Parse() to use, the
compiler doesn't even have a clue whether to use integer or floating point
multiplication.
That's no big problem it should just give an error like it does with current
ambiguous overloads.
The other problem with this is that it most definitely doesn't encourage
good object oriented design.


How is that?

Michael
Nov 17 '05 #12

P: n/a

"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:uD**************@TK2MSFTNGP14.phx.gbl...
"Chris Priede" <pr****@panix.com> wrote in message
news:OG******************@TK2MSFTNGP14.phx.gbl...
Ok. Now, let's pretend that we also have some overloaded methods that
take different argument types, say:

void Print(int i)
void Print(double i)

Now, someone comes along and writes:

int x = 5;

Print( x * Parse(something) );

Besides not having any clue which Print() and which Parse() to use, the
compiler doesn't even have a clue whether to use integer or floating
point multiplication.


That's no big problem it should just give an error like it does with
current ambiguous overloads.


Currently, errors due to ambiguious overloads are quite rare, what you are
proposing would bring them into the forefront. You also have failed to
provide any workable syntax that differentiates between casting the return
value to a given type and selecting a given return type.

Now, I know it sounds easy, but its not. Overload selection is a complex
beast already, expanding it so that the method call is related to factors
outside of the method itself would compliate a compiler considerably.
Currently the language works from the inside out. To determine the
particular method the caller wants to call you only need the method call
itself:

Parse(something);

that tells the compiler everything it needs to know. The call expression is
simple, life is good.

Now, you add into that a requirement to know the type of the variable the
return type is going to be assigned to or the parameter type it will be
passed to. This forces the compiler to have to be able to see

int x = Parse(something);

The method call is not individually resolvable, it becomes an expression
that means nothing concrete without being contained within another
expression(I do not believe this issue exists *anywhere* else in the
language, but I'm not certain). The compiler is harder to write, the
language harder to learn. Bam, instant complexity at the base level of the
compiler.

Now, lets take this a step further and produce a few difficult or impossible
to resolve scenarios.

Given:
int Parse(string value);
double Parse(string value);

int Calc(int value);
double Calc(double value);

double d = Calc(Parse("15")):

When the compiler takes a look at the call to Parse it cannot resolve what
overload to call. The compile rmust then take a look at the parameter type
for Calc, which also cannot be resolved atomicall ywithout knowing the
resolved return type of the Parse call, so you have yet another unresolved
method. You step back a little farther and finally discover an assignment
meaning you can determine the desired return type of Calc, and in this
example, determine which overload of Parse must be called. However,
considering the compiler without return type overloads would have had no
trouble doing this, what is the cost in complexity?

Return type overloading where the return type is chosen based on assignment
is going to atleast double(and probably treble) the complexity of overload
resolution, which is already one of the trickest parts of the language.

Given:
int Parse(string value);
double Parse(string value);
string Parse(string value);

int Calc(int value);
double Calc(double value);
double Calc(string value);

double d = Calc(Parse("apple")):

In this circumstance the call to Parse cannot be resolved on its own, thus
the call to Calc cannot be resolved on its own, and since there are two calc
overloads that return double, resolution fails.
Is this really as simple as you think it is? I've not even started on the
possible issues with generics and anonymous methods and the language itself
is already considerably more complex. Realistically implementing return type
overloading, IMHO, requires a mechanism to manually select the override
instead of relying on automatic selection that ignores casts and
converstions.
Nov 17 '05 #13

P: n/a

"Mike Schilling" <ms*************@hotmail.com> wrote in message
news:er**************@TK2MSFTNGP10.phx.gbl...

"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:ex**************@TK2MSFTNGP14.phx.gbl...
"mdb" <m_b_r_a_y@c_t_i_u_s_a__d0t__com> wrote in message
news:Xn****************************@207.46.248.16. ..
Because the function call and assigning the result are two completely
different things.


In VB6 the return value was just another parameter under the hood. The
actual return value was the error code, which I presume is the same in
C#. Someone correct me if i'm wrong.


Sorry, you're wrong about C#.


And wrong about VB6 too, what you describe is what happens when you call a
COM method.

Willy.
Nov 17 '05 #14

P: n/a
TJB replied to:
The method call is not individually resolvable, it becomes an expression that means nothing concrete without being contained within another
expression(I do not believe this issue exists *anywhere* else in the
language, but I'm not certain). The compiler is harder to write, the
language harder to learn. Bam, instant complexity at the base level of the compiler.


The lack of this feature makes the language a lot less elegant. Little
traversal methods such as T Next(), T First(), T Last(), etc, means
that an entire style of an immutable navigator chumpy becomes pretty
much impossible to write. I would question the idea of the language
being "harder to learn". It is actually more intuitive to let the
return type be of anything just the way the rest of the parameters are.

Microsoft has billions of dollars and since they jack up the price of
Visual Studio with every release they ought to suck it up and get some
people that can write compilers rather than whine and wring hands about
excessive complexity!

Nov 17 '05 #15

P: n/a

Microsoft has billions of dollars and since they jack up the price of
Visual Studio with every release they ought to suck it up and get some
people that can write compilers rather than whine and wring hands about
excessive complexity!


Hey calm down! If you don't like it the way it is. Use another programming
language and another framework. Use Java - oh, wow, same problem there...
Use C++ - oh, again, same problem there...

--
Claudio Grazioli
http://www.grazioli.ch
http://www.grazioli.ch/HommingbergerGepardenforelle/
Nov 17 '05 #16

P: n/a
stork wrote:
The lack of this feature makes the language a lot less elegant. Little


Perhaps you should try a language that does context-sensitive
overloading. The only *language* i know of that has this is perl, where
functions behave differently depening on whether they are in a scalar or
array context.

--
Helge Jensen
mailto:he**********@slog.dk
sip:he**********@slog.dk
-=> Sebastian cover-music: http://ungdomshus.nu <=-
Nov 17 '05 #17

P: n/a
"Willy Denoyette [MVP]" <wi*************@telenet.be> wrote in message
news:Oh**************@TK2MSFTNGP10.phx.gbl...
And wrong about VB6 too, what you describe is what happens when you call a
COM method.


I'd bet my house I'm right. The only exception is modules but anything in a
class, form or usercontrol works as I described even if the class is
private.

Michael
Nov 17 '05 #18

P: n/a
"Claudio Grazioli" <ne********@gmx-ist-cool.de> wrote in message
news:3y***************************@40tude.net...
Hey calm down! If you don't like it the way it is. Use another programming
language and another framework. Use Java - oh, wow, same problem there...
Use C++ - oh, again, same problem there...


I noticed you described it has a problem. :-)

Michael
Nov 17 '05 #19

P: n/a
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:%2****************@TK2MSFTNGP15.phx.gbl...
Now, you add into that a requirement to know the type of the variable the
return type is going to be assigned to or the parameter type it will be
passed to. This forces the compiler to have to be able to see

int x = Parse(something);
The compiler is going to need to know the return type anyway. I don't see it
much different from:

Parse(Something, ref x);
The method call is not individually resolvable, it becomes an expression
that means nothing concrete without being contained within another
expression(I do not believe this issue exists *anywhere* else in the
language, but I'm not certain). The compiler is harder to write, the
language harder to learn. Bam, instant complexity at the base level of the
compiler.
Overloading makes the language harder to learn, as does inheritance and
interfaces, we'd better leave those out too. :-)
Now, lets take this a step further and produce a few difficult or
impossible to resolve scenarios.

Given:
int Parse(string value);
double Parse(string value);

int Calc(int value);
double Calc(double value);

double d = Calc(Parse("15")):

When the compiler takes a look at the call to Parse it cannot resolve what
overload to call. The compile rmust then take a look at the parameter type
for Calc, which also cannot be resolved atomicall ywithout knowing the
resolved return type of the Parse call, so you have yet another unresolved
method. You step back a little farther and finally discover an assignment
meaning you can determine the desired return type of Calc, and in this
example, determine which overload of Parse must be called. However,
considering the compiler without return type overloads would have had no
trouble doing this, what is the cost in complexity?
But it can do it and it makes sense to the programmer for it to be double
all the way through.
Is this really as simple as you think it is? I've not even started on the
possible issues with generics and anonymous methods and the language
itself is already considerably more complex. Realistically implementing
return type overloading, IMHO, requires a mechanism to manually select the
override instead of relying on automatic selection that ignores casts and
converstions.
I'm sure it can get complex but in any case it can't resolve the call it
should just say so. Programmers would know to specify the return type in the
necessary cases. Maybe something like double d = Calc((double)Parse("15")):
could be used.

Nov 17 '05 #20

P: n/a
In message <uP**************@tk2msftngp13.phx.gbl>, Michael C
<mc*****@NOSPAMoptushome.com.au> writes
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in

The method call is not individually resolvable, it becomes an expression
that means nothing concrete without being contained within another
expression(I do not believe this issue exists *anywhere* else in the
language, but I'm not certain). The compiler is harder to write, the
language harder to learn. Bam, instant complexity at the base level of the
compiler.


Overloading makes the language harder to learn, as does inheritance and
interfaces, we'd better leave those out too. :-)


It's a trade-off of utility against complexity. I'd be on the "not worth
it" side of the debate. I can't see that it would be a useful enough
feature to be worthwhile, and I think that if C# had it, and I found
myself using it, I'd immediately suspect that I needed to refactor the
code.

If the different versions of the method were semantically identical, you
would just be hiding a cast or conversion. Assuming simple types, I can
only see that you might want to encapsulate that if it were doing
something specific to the context of the class. If that were the case
you could create non-intuitive anomalies; if int Foo(){} and float
Foo(){} were overloads with different return types, and int Foo(){} did
something other than cast a float to an int, you may end up with

(int)Foo() != (int)(float)Foo()

If the methods returned instances of classes of my own making, I'd look
at returning a supertype.

If they were not semantically identical, they should have had different
names.

--
Steve Walker
Nov 17 '05 #21

P: n/a

"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:uP**************@tk2msftngp13.phx.gbl...
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:%2****************@TK2MSFTNGP15.phx.gbl...
Now, you add into that a requirement to know the type of the variable the
return type is going to be assigned to or the parameter type it will be
passed to. This forces the compiler to have to be able to see

int x = Parse(something);
The compiler is going to need to know the return type anyway. I don't see
it much different from:

Parse(Something, ref x);


Why would you see it as that? The two are semantically different.

Anyway, yes the compiler already knows the return type, but it is capable fo
determing the return type from the method call alone. To overload on return
type would require more information than the method call alone can provide.
The method call is not individually resolvable, it becomes an expression
that means nothing concrete without being contained within another
expression(I do not believe this issue exists *anywhere* else in the
language, but I'm not certain). The compiler is harder to write, the
language harder to learn. Bam, instant complexity at the base level of
the compiler.


Overloading makes the language harder to learn, as does inheritance and
interfaces, we'd better leave those out too. :-)


You realize, everyone uses this argument for everything. This is as
effective of a reason for insisting that the language must require case to
change for every letter of an identifier as it is for this.

As Steve Walker points out, its utility verse complexity. Inheritance and
interfaces offer significant utility with moderate complexity whereas return
type overloading provides minimal utliity with significant complexity.

Given:
int Parse(string value);
double Parse(string value);

int Calc(int value);
double Calc(double value);

double d = Calc(Parse("15")):

When the compiler takes a look at the call to Parse it cannot resolve
what overload to call. The compile rmust then take a look at the
parameter type for Calc, which also cannot be resolved atomicall ywithout
knowing the resolved return type of the Parse call, so you have yet
another unresolved method. You step back a little farther and finally
discover an assignment meaning you can determine the desired return type
of Calc, and in this example, determine which overload of Parse must be
called. However, considering the compiler without return type overloads
would have had no trouble doing this, what is the cost in complexity?


But it can do it and it makes sense to the programmer for it to be double
all the way through.


It does? To me it doesn't in *ANY* way tell me that Parse() should be
returnign a double without knowing that the specific Calc method is tied to
the type of the return type. I don't think that is clear in any way. That is
like saying that I can tell from a baby what its grandfather looks like.
Sure, its possible, but its a shot in the dark unless you already know the
answer.

And,then, what does something like

this.Property = Calc(Parse(GetString()))

mean? The type is hidden and all three method calls are terribly ambigious
from the programmers point of view.

Let me ask you this, have you *ever* used an OO langauge that allows return
type overloading, especially one that determines the method to call
automatically?
Is this really as simple as you think it is? I've not even started on the
possible issues with generics and anonymous methods and the language
itself is already considerably more complex. Realistically implementing
return type overloading, IMHO, requires a mechanism to manually select
the override instead of relying on automatic selection that ignores casts
and converstions.


I'm sure it can get complex but in any case it can't resolve the call it
should just say so. Programmers would know to specify the return type in
the necessary cases. Maybe something like double d =
Calc((double)Parse("15")): could be used.


Yet that is ambigious at best, what do you do when you end up needing code
you can't write because the compiler cannot resolve what you are doing?

And, more importantly, *WHY* is all this better than just DoubleFromString()
and IntFromSTring() ?
Nov 17 '05 #22

P: n/a
"Steve Walker" <st***@otolith.demon.co.uk> wrote in message
news:$X**************@otolith.demon.co.uk...
It's a trade-off of utility against complexity. I'd be on the "not worth
it" side of the debate. I can't see that it would be a useful enough
feature to be worthwhile, and I think that if C# had it, and I found
myself using it, I'd immediately suspect that I needed to refactor the
code.
It could be made a lot simpler by giving an error if the return type was not
completely obvious. eg Parse(Calc("1.0")) could give an error unless it was
specified as Parse((int)Calc("1.0")) or int x = Calc("1.0").
If the different versions of the method were semantically identical, you
would just be hiding a cast or conversion. Assuming simple types, I can
only see that you might want to encapsulate that if it were doing
something specific to the context of the class. If that were the case you
could create non-intuitive anomalies; if int Foo(){} and float Foo(){}
were overloads with different return types, and int Foo(){} did something
other than cast a float to an int, you may end up with

(int)Foo() != (int)(float)Foo()
Same problem can potentially apply with current overloads though so I don't
see it as a problem.

If the methods returned instances of classes of my own making, I'd look at
returning a supertype.

If they were not semantically identical, they should have had different
names.

--
Steve Walker

Nov 17 '05 #23

P: n/a
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:ef**************@tk2msftngp13.phx.gbl...
Why would you see it as that? The two are semantically different.
There is a difference but there is also a similarity. Did you fail to see
it?
Anyway, yes the compiler already knows the return type, but it is capable
fo determing the return type from the method call alone. To overload on
return type would require more information than the method call alone can
provide.
It would still be able to achieve it.
You realize, everyone uses this argument for everything. This is as
effective of a reason for insisting that the language must require case to
change for every letter of an identifier as it is for this.

As Steve Walker points out, its utility verse complexity. Inheritance and
interfaces offer significant utility with moderate complexity whereas
return type overloading provides minimal utliity with significant
complexity.
In the end it is a matter of opinion though if the complexity outweighs the
gain.
It does? To me it doesn't in *ANY* way tell me that Parse() should be
returnign a double without knowing that the specific Calc method is tied
to the type of the return type. I don't think that is clear in any way.
That is like saying that I can tell from a baby what its grandfather looks
like. Sure, its possible, but its a shot in the dark unless you already
know the answer.

And,then, what does something like

this.Property = Calc(Parse(GetString()))

mean? The type is hidden and all three method calls are terribly ambigious
from the programmers point of view.
It probably is but *you* wrote the ambiguous code. If you think it's a
problem then don't write ambiguous code.
Let me ask you this, have you *ever* used an OO langauge that allows
return type overloading, especially one that determines the method to call
automatically?
Of course not.
Yet that is ambigious at best,
No more ambiguous as current overloads.
what do you do when you end up needing code you can't write because the
compiler cannot resolve what you are doing?
I don't see how that could possible happen.
And, more importantly, *WHY* is all this better than just
DoubleFromString() and IntFromSTring() ?


For the same reason current overloads are better.

Michael
Nov 17 '05 #24

P: n/a
And, more importantly, *WHY* is all this better than just
DoubleFromString() and IntFromSTring() ?


For the same reason current overloads are better.


Current overloads have visible, obvious differences though

Method(a)
Method(a,b)

obviously two different methods

Method(a)
Method(a)

thats not obvious. If you consider it better only in theory, I'll agree with
you, but I do not htink it offers *ANY* value within a language such as C#.
I suspect it'd hurt alot more than it'd help.

I'm going to end this discussion here as it has degenerated to "it can be
done so why isn't it". It isn't because its a bad idea and will turn your
code into a nightmare, if you can't see that or dont share the opinion,
fine, just accept that I think return type overloading with automatic return
type determination one of the worst possible features one could add to a
language.
Nov 17 '05 #25

P: n/a
Michael C <mc*****@NOSPAMoptushome.com.au> wrote:
Let me ask you this, have you *ever* used an OO langauge that allows
return type overloading, especially one that determines the method to call
automatically?


Of course not.


Out of interest, why do you think that is? You're not the first person
to come up with this idea, so if it's such a good idea, why do you
think it hasn't made it into any languages?

While I can see it would allow us to get away from having lots of
methods with different names but the same parameter types, that's the
*only* advantage I can see, and that situation comes up pretty rarely
in my experience. I don't think it justitifies making the language
significantly more complicated.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #26

P: n/a
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:OF**************@TK2MSFTNGP12.phx.gbl...
Current overloads have visible, obvious differences though

Method(a)
Method(a,b)

obviously two different methods

Method(a)
Method(a)

thats not obvious.
Of course it's not obvious, you haven't written the entire signature ffs!!!
*You* have left off the part that is different!!! I could use the same
stupid arguement against the current overloads. What's the difference
between

Method
Method

gee, we better not have overloads :-)
If you consider it better only in theory, I'll agree with you, but I do
not htink it offers *ANY* value within a language such as C#. I suspect
it'd hurt alot more than it'd help.
It offers the same value current overload offer, reducing the number of
names for a function. If you think there is no value you are not thinking
straight.
I'm going to end this discussion here as it has degenerated to "it can be
done so why isn't it". It isn't because its a bad idea and will turn your
code into a nightmare,
It could potentially turn stupid people's code into a nightmare but likewise
any other feature.
if you can't see that or dont share the opinion, fine, just accept that I
think return type overloading with automatic return type determination one
of the worst possible features one could add to a language.


I accept that is your opinion.

Michael
Nov 17 '05 #27

P: n/a

"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:uC**************@TK2MSFTNGP15.phx.gbl...
"Willy Denoyette [MVP]" <wi*************@telenet.be> wrote in message
news:Oh**************@TK2MSFTNGP10.phx.gbl...
And wrong about VB6 too, what you describe is what happens when you call
a COM method.


I'd bet my house I'm right. The only exception is modules but anything in
a class, form or usercontrol works as I described even if the class is
private.

Michael


Mind to prove your claim? That is prove that VB6 uses COM interfaces when
accessing regular VB6 Classes/Methods, note I'm NOT talking about accessing
VB6 authored Com/ActiveX classes (usercontrol) or toolbox classes (like
Forms, Listboxes etc...) from VB6 clients, just plain simple VB6 Classes.

Willy.
Nov 17 '05 #28

P: n/a
In message <eT**************@TK2MSFTNGP10.phx.gbl>, Michael C
<mc*****@NOSPAMoptushome.com.au> writes
"Steve Walker" <st***@otolith.demon.co.uk> wrote in message
news:$X**************@otolith.demon.co.uk...
It's a trade-off of utility against complexity. I'd be on the "not worth
it" side of the debate. I can't see that it would be a useful enough
feature to be worthwhile, and I think that if C# had it, and I found
myself using it, I'd immediately suspect that I needed to refactor the
code.


It could be made a lot simpler by giving an error if the return type was not
completely obvious. eg Parse(Calc("1.0")) could give an error unless it was
specified as Parse((int)Calc("1.0")) or int x = Calc("1.0").


My concern is more that if I found myself using it, I'd wonder whether
my design was flawed. I can see a small set of cases where it would be
harmless; for instance I have a class which wraps a DataRow and has
methods like:

public int GetInt(string name)
public DateTime GetDateTime(string name)
public string GetString(string name)
public bool GetBool(string name)

etc.

The sole purpose of that class is to handle DBNull values in a
particular way, and the methods are mutually exclusive for any given
type; if the underlying database data type isn't what you think it is,
you'll get an exception.

I think that in anything other than a simple utility class, overloaded
return types would be a code smell, and I'd want to look at why the
method name was so ambiguous. If it's reasonable to overload return
types, it's probably more reasonable to have a single method returning a
superclass of the overloaded types. If there isn't a sensible superclass
for the overloaded types, the overloads are returning totally different
things, and should probably be different methods.
If the different versions of the method were semantically identical, you
would just be hiding a cast or conversion. Assuming simple types, I can
only see that you might want to encapsulate that if it were doing
something specific to the context of the class. If that were the case you
could create non-intuitive anomalies; if int Foo(){} and float Foo(){}
were overloads with different return types, and int Foo(){} did something
other than cast a float to an int, you may end up with

(int)Foo() != (int)(float)Foo()


Same problem can potentially apply with current overloads though so I don't
see it as a problem.


What, in terms of overloading operators to define casts? In that
situation, you're doing something subtly different; what you are
achieving as a user of the code is more transparent. They are also
something I'd use with care. I wouldn't want to represent the
calculation of a scalar quantity from a vector quantity with a cast, for
example.

--
Steve Walker
Nov 17 '05 #29

P: n/a
"Willy Denoyette [MVP]" <wi*************@telenet.be> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...
Mind to prove your claim? That is prove that VB6 uses COM interfaces when
accessing regular VB6 Classes/Methods, note I'm NOT talking about
accessing VB6 authored Com/ActiveX classes (usercontrol) or toolbox
classes (like Forms, Listboxes etc...) from VB6 clients, just plain simple
VB6 Classes.


No problem, although I didn't say it uses COM interfaces for everything, I
said that it puts the return type as the last parameter and the actual
return value is the error information. There may be other complexities of
COM that it doesn't implement underneath.

The reason I know it does this is because I was once mucking around with
getting API callbacks to go directly into classes in vb4. I created some
assembly code in a byte array that would fix up the stack and call the
function in the class. I noticed that it didn't matter if the function with
public, private or friend or if the class was public or private I was still
able to find it in the VTable and call it in exactly the same way. The only
difference was that private functions appeared after the public ones. In all
cases a function like this:

Public Function AddOne(ByVal SomeParam as Long) as Long

would actually be something like (I'm not sure of the correct syntax)

Public Function AddOne(ByVal This as Long, ByVal SomeParam As Long, ByRef
RetVal as Long) as HRESULT

Michael
Nov 17 '05 #30

P: n/a
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Out of interest, why do you think that is? You're not the first person
to come up with this idea, so if it's such a good idea, why do you
think it hasn't made it into any languages?
For some reason language writers seem to like to keep things consistant with
previous languages.
While I can see it would allow us to get away from having lots of
methods with different names but the same parameter types, that's the
*only* advantage I can see,
That's the only advantage of the current overloads.
and that situation comes up pretty rarely
in my experience. I don't think it justitifies making the language
significantly more complicated.


I don't see it as much greater complexity. For example if they'd
implemeneted it for the datareader you might have to write it as
(int)reader.Value(1) instead of reader.GetInt(1). If the compiler complained
in any situation that was not dead obvious then it could work quite well.

Michael
Nov 17 '05 #31

P: n/a
Michael C <mc*****@NOSPAMoptushome.com.au> wrote:
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Out of interest, why do you think that is? You're not the first person
to come up with this idea, so if it's such a good idea, why do you
think it hasn't made it into any languages?


For some reason language writers seem to like to keep things consistant with
previous languages.


Given how many experimental languages there are, that seems unlikely to
me. There are plenty of languages which try lots of different things,
and the best concepts usually work their way into the mainstream
eventually. I think there's a good reason for overloading by return
type not making it - it adds too much complexity for too little
benefit.
While I can see it would allow us to get away from having lots of
methods with different names but the same parameter types, that's the
*only* advantage I can see,


That's the only advantage of the current overloads.


The difference is how often that's useful compared with how often
overloading by return type would be useful though. Look at all the
examples of overloading by parameters in the framework, and then think
of how many places overloading by return type would really be useful.
Places I can think of:

DataReader
Convert
BitConverter
Stream
TextReader
BinaryReader
Marshal

Frankly, in all those places I think having the instantly readable an
unambiguous calls is often more of a blessing than a curse. Arguably
having more explicit alternatives to overloading for writing in some of
the above would be a better way to improve things - and at no language
complexity cost.
and that situation comes up pretty rarely
in my experience. I don't think it justitifies making the language
significantly more complicated.


I don't see it as much greater complexity. For example if they'd
implemeneted it for the datareader you might have to write it as
(int)reader.Value(1) instead of reader.GetInt(1). If the compiler complained
in any situation that was not dead obvious then it could work quite well.


It's a fundamentally more complicated language though, as the type of
an expression would depend on its context in a way in which it simply
doesn't now.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #32

P: n/a
Jon Skeet [C# MVP] wrote:
For some reason language writers seem to like to keep things consistant with
previous languages.


Overloading on the return type means that you cannot determine the type
of an expression without looking at it's context.

That is undesireable because it prevents using compositional recursion
to evaluate the type of the expressions of the program.

As a small taste of the problem, given definitions:

X f(Y);
Y f(X);
X x; Y y;

Which error would you give on:

y = f(f(x))

Hint: there are two possible errors:

1: cannot covent argument 1 of "X f(Y)" from type X to type Y
2: cannot assign type X to type Y

Depending on whether you overload by the arguments or the return-type.

Besides, if you wish to overload on the "return-type", just use:

f(out X x, Y y);
f(out Y y, X x);

I suggest trying to write a staticly typed compiler to get to really
understand this problem.

--
Helge Jensen
mailto:he**********@slog.dk
sip:he**********@slog.dk
-=> Sebastian cover-music: http://ungdomshus.nu <=-
Nov 17 '05 #33

P: n/a
Yeah, I'll probably have to go write my own! As they say, put up or
shut up!

Nov 17 '05 #34

P: n/a

"Helge Jensen" <he**********@slog.dk> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...
Jon Skeet [C# MVP] wrote:
For some reason language writers seem to like to keep things consistant
with previous languages.


Overloading on the return type means that you cannot determine the type of
an expression without looking at it's context.

That is undesireable because it prevents using compositional recursion to
evaluate the type of the expressions of the program.

As a small taste of the problem, given definitions:

X f(Y);
Y f(X);
X x; Y y;

Which error would you give on:

y = f(f(x))

Hint: there are two possible errors:

1: cannot covent argument 1 of "X f(Y)" from type X to type Y
2: cannot assign type X to type Y


Or 3: f(x) is ambiguous.

Overloading on return type is (IMHO) a bad idea, and allowing it in
situations where the return type isn't completely unambiguous is fatal.
Even
y = f((Y)f(x));

is problematical: what if there's a conversion from X to Y?
Nov 17 '05 #35

P: n/a
This is about control over types.

Right now we as developers want to hold all the cards on type control,
and I'm wondering if that complexity is really worth it.

Consider the example:

y = f((Y)f(X));

to evaluate the type for this, start with the type of y.

Then, select the f() whose return type matches y.

For the inside call, you force, by cast, the selection of an f(X) that
returns a Y.

At this point, you can have an error. There may not be an f() that
satisfies the type requirements that we established. Compilation
halts.

Nov 17 '05 #36

P: n/a
"Helge Jensen" <he**********@slog.dk> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...
Which error would you give on:

y = f(f(x))
Very simple. You give an error that states it is ambiguos, forcing the
programmer to specify the return type they wish to use. I don't see this as
that difficult.
I suggest trying to write a staticly typed compiler to get to really
understand this problem.


Irrelevant, it is achievable by ms.

Michael
Nov 17 '05 #37

P: n/a
"Helge Jensen" <he**********@slog.dk> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...
Which error would you give on:

y = f(f(x))


This is going around in circles. Everyone keeps saying it would be overly
ambiguous. I respond by saying that ambiguity can be got around by forcing
the programmer to specify the return type in any case where there is more
than one option, eg (int)Parse("1"). Everyone keeps repeating that it will
be too ambiguous without responding to my point. Must be a good point :-)

Michael
Nov 17 '05 #38

P: n/a
Michael C <mc*****@NOSPAMoptushome.com.au> wrote:
"Helge Jensen" <he**********@slog.dk> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...
Which error would you give on:

y = f(f(x))


This is going around in circles. Everyone keeps saying it would be overly
ambiguous. I respond by saying that ambiguity can be got around by forcing
the programmer to specify the return type in any case where there is more
than one option, eg (int)Parse("1"). Everyone keeps repeating that it will
be too ambiguous without responding to my point. Must be a good point :-)


Even when it's not actually ambiguous though, it's likely to be harder
to read - it would take longer to work out what's actually going on.
The overloading rules - which are complicated already - would become
significantly more complicated.

The CLR does support it though IIRC, so I suggest if you still think
it's a good idea, take the Mono compiler and modify it to do what you
want it to do. Use it for a few months and see whether you think it's a
good idea in practice, and then tell us all how you've got on...

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #39

P: n/a


Michael C wrote:
"Helge Jensen" <he**********@slog.dk> wrote in message
This is going around in circles. Everyone keeps saying it would be overly
ambiguous. I respond by saying that ambiguity can be got around by forcing
Im not saying it would be too ambigous.
the programmer to specify the return type in any case where there is more
than one option, eg (int)Parse("1"). Everyone keeps repeating that it will
be too ambiguous without responding to my point. Must be a good point


The newsgroup is not a good place to teach compiler theory. Take a
course on it.

There are *deep* problems with not only the ambiguity of the language,
but inherent problems with defining the type-validation algorithm.

Have fun.

--
Helge Jensen
mailto:he**********@slog.dk
sip:he**********@slog.dk
-=> Sebastian cover-music: http://ungdomshus.nu <=-
Nov 17 '05 #40

P: n/a
Very deep problems.

Consider the example.

y = F(F(x))

Given y is type A, in a system where there are types A and B.

F(x) is defined for

A F( A )
A F( B )
B F( A )

y = F(F(x))

Let x be of type A

can resolve to either

y = F( F<B>( A ) )

or

y = F( F<A>( A ) )

This is actually avoidable. The language would force a rule that says
a function return may not be used as a parameter to another function.
You would always have to assign through temporaries and that would be
safe. The only problem that comes into play though, would be for
overloads of things like the . or the -> operator, which are
effectively functions themselves.

If I have X -> operator
and Y -> operator

Then I would not be able to write X->Y->Z without introducing
ambiguity. You would then have to write something with a lot of
temporaries.

A Y = X->Y
B Z = Z->Y

which, honestly, is a lot of typing, even though it might make for
better practice as it is easier to debug.

Nov 17 '05 #41

P: n/a
In that case it is simple, notions such as object x should drive the
type selection.

string x = Foo() + Foo()

gives you the overload for string, and likewise for int.

Nov 17 '05 #42

P: n/a
Cast operator overloads do take in account the return type.

"stork" <tb******@mightyware.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
Very deep problems.

Consider the example.

y = F(F(x))

Given y is type A, in a system where there are types A and B.

F(x) is defined for

A F( A )
A F( B )
B F( A )

y = F(F(x))

Let x be of type A

can resolve to either

y = F( F<B>( A ) )

or

y = F( F<A>( A ) )

This is actually avoidable. The language would force a rule that says
a function return may not be used as a parameter to another function.
You would always have to assign through temporaries and that would be
safe. The only problem that comes into play though, would be for
overloads of things like the . or the -> operator, which are
effectively functions themselves.

If I have X -> operator
and Y -> operator

Then I would not be able to write X->Y->Z without introducing
ambiguity. You would then have to write something with a lot of
temporaries.

A Y = X->Y
B Z = Z->Y

which, honestly, is a lot of typing, even though it might make for
better practice as it is easier to debug.

Nov 17 '05 #43

P: n/a
They force a return type.

Nov 17 '05 #44

P: n/a
"stork" <tb******@mightyware.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
This is actually avoidable. The language would force a rule that says
a function return may not be used as a parameter to another function.


of it could just be written as Calc((int)Parse("1"))

Michael
Nov 17 '05 #45

P: n/a
"stork" <tb******@mightyware.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
This is actually avoidable. The language would force a rule that says
a function return may not be used as a parameter to another function.


of it could just be written as Calc((int)Parse("1"))

Michael
Nov 17 '05 #46

P: n/a

"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:es**************@tk2msftngp13.phx.gbl...
"stork" <tb******@mightyware.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
This is actually avoidable. The language would force a rule that says
a function return may not be used as a parameter to another function.


of it could just be written as Calc((int)Parse("1"))


And you'd know that this case indicates return type rather than being a cast
of

double Parse(String s)

because ... ?

Casts already mean at least two different things in C#

double d;
Object o;

(int)d
remove the fractional part of d, resulting in an int

(int)o
leave o unchanged, but throw an exception if it's not an int

Note that:

Object o = 12.2;
Console.WriteLine((int)o);

throws an exception, because "throw an exception if it's not an int" is
enforced strictly. (I had to try it to be sure.)

Now you're adding another meaning, which is "give the compiler a hint about
which overload to choose". I'm less than enthusiastic about making an
already complex situation more so.
Nov 17 '05 #47

P: n/a

"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:es**************@tk2msftngp13.phx.gbl...
"stork" <tb******@mightyware.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
This is actually avoidable. The language would force a rule that says
a function return may not be used as a parameter to another function.


of it could just be written as Calc((int)Parse("1"))


And you'd know that this case indicates return type rather than being a cast
of

double Parse(String s)

because ... ?

Casts already mean at least two different things in C#

double d;
Object o;

(int)d
remove the fractional part of d, resulting in an int

(int)o
leave o unchanged, but throw an exception if it's not an int

Note that:

Object o = 12.2;
Console.WriteLine((int)o);

throws an exception, because "throw an exception if it's not an int" is
enforced strictly. (I had to try it to be sure.)

Now you're adding another meaning, which is "give the compiler a hint about
which overload to choose". I'm less than enthusiastic about making an
already complex situation more so.
Nov 17 '05 #48

P: n/a
"Mike Schilling" <ms*************@hotmail.com> wrote in message
news:eG**************@tk2msftngp13.phx.gbl...
Now you're adding another meaning, which is "give the compiler a hint
about which overload to choose".
Isn't this the same thing:

DoSomething((long)1);

?
I'm less than enthusiastic about making an already complex situation more
so.


I don't see it as that complex. Programmers have already learnt to handle
the types of parameters into a function. A lot of people have said it would
be too complex for ms but I'm sure they could manage it.

Michael
Nov 17 '05 #49

P: n/a
"Mike Schilling" <ms*************@hotmail.com> wrote in message
news:eG**************@tk2msftngp13.phx.gbl...
Now you're adding another meaning, which is "give the compiler a hint
about which overload to choose".
Isn't this the same thing:

DoSomething((long)1);

?
I'm less than enthusiastic about making an already complex situation more
so.


I don't see it as that complex. Programmers have already learnt to handle
the types of parameters into a function. A lot of people have said it would
be too complex for ms but I'm sure they could manage it.

Michael
Nov 17 '05 #50

59 Replies

This discussion thread is closed

Replies have been disabled for this discussion.