469,317 Members | 1,697 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,317 developers. It's quick & easy.

Should this type of method overload work in C#?

public class Base
{
}

public class Derived : Base
{
}

public class Service
{
public void Send(Base baseObject)
{
// send baseObject
Console.Out.WriteLine("Called public void Send(Base baseObject)
signature");
}

public void Send(Subclass derivedObject)
{
// send derivedObject
Console.Out.WriteLine("Called public void Send(Subclass derivedObject)
signature");
}
}

public class MainClass
{
public static void Main(string[] args)
{
Base baseObject = new Base();
Derived derivedObject = new Derived();

Service service = new Service();

// this calls public void Send(Base baseObject) as expected
service.Send(baseObject);

// this calls public void Send(Base baseObject),
// but it should call public void Send(Subclass derivedObject),
// shouldn't it???
service.Send(derivedObject);
}
}

I expect this to work, but I tested it at runtime, verifying that the
instance is of the Derived class and it still calls the signature with the
base class.

thanks,

Dave Raskin
Nov 17 '05 #1
19 1710
Howdy. I believe I got it to work properly (as you expected) for me.
Here's the code I used (slightly modified to get it to compile). Output at
the end.
//--------------------------------------------------------------start code
using System;

public class Base
{
}

public class Derived : Base
{
}

public class Service
{
public void Send(Base baseObject)
{
// send baseObject
Console.WriteLine("Called public void Send(Base baseObject) signature");
}

public void Send(Derived derivedObject)
{
// send derivedObject
Console.WriteLine("Called public void Send(Subclass derivedObject)
signature");
}
}

public class MainClass
{
public static void Main(string[] args)
{
Base baseObject = new Base();
Derived derivedObject = new Derived();

Service service = new Service();

// this calls public void Send(Base baseObject) as expected
service.Send(baseObject);

// this calls public void Send(Base baseObject),
// but it should call public void Send(Subclass derivedObject),
// shouldn't it???
service.Send(derivedObject);
}
}
//--------------------------------------------------------------end code
And here's the output I see.

C:\temp>basetesting
Called public void Send(Base baseObject) signature
Called public void Send(Subclass derivedObject) signature

C:\temp>
Nov 17 '05 #2
Howdy. I believe I got it to work properly (as you expected) for me.
Here's the code I used (slightly modified to get it to compile). Output at
the end.
//--------------------------------------------------------------start code
using System;

public class Base
{
}

public class Derived : Base
{
}

public class Service
{
public void Send(Base baseObject)
{
// send baseObject
Console.WriteLine("Called public void Send(Base baseObject) signature");
}

public void Send(Derived derivedObject)
{
// send derivedObject
Console.WriteLine("Called public void Send(Subclass derivedObject)
signature");
}
}

public class MainClass
{
public static void Main(string[] args)
{
Base baseObject = new Base();
Derived derivedObject = new Derived();

Service service = new Service();

// this calls public void Send(Base baseObject) as expected
service.Send(baseObject);

// this calls public void Send(Base baseObject),
// but it should call public void Send(Subclass derivedObject),
// shouldn't it???
service.Send(derivedObject);
}
}
//--------------------------------------------------------------end code
And here's the output I see.

C:\temp>basetesting
Called public void Send(Base baseObject) signature
Called public void Send(Subclass derivedObject) signature

C:\temp>
Nov 17 '05 #3
Hi Dave,

Service doesn't have an overload with a Derived parameter, so the compiler
used a best match that took the overload with the Base parameter. From the
information you've given, I can't tell what SubClass is. However, if you
change the definition of Send(SubClass derivedObject) to this, you could get
what you expect:

public void Send(Derived derivedObject)
{
// send derivedObject
Console.Out.WriteLine("Called public void Send(Derived derivedObject)
signature");
}

Joe
--
http://www.csharp-station.com

"Dave Raskin" <Dave Ra****@discussions.microsoft.com> wrote in message
news:0A**********************************@microsof t.com...
public class Base
{
}

public class Derived : Base
{
}

public class Service
{
public void Send(Base baseObject)
{
// send baseObject
Console.Out.WriteLine("Called public void Send(Base baseObject)
signature");
}

public void Send(Subclass derivedObject)
{
// send derivedObject
Console.Out.WriteLine("Called public void Send(Subclass derivedObject)
signature");
}
}

public class MainClass
{
public static void Main(string[] args)
{
Base baseObject = new Base();
Derived derivedObject = new Derived();

Service service = new Service();

// this calls public void Send(Base baseObject) as expected
service.Send(baseObject);

// this calls public void Send(Base baseObject),
// but it should call public void Send(Subclass derivedObject),
// shouldn't it???
service.Send(derivedObject);
}
}

I expect this to work, but I tested it at runtime, verifying that the
instance is of the Derived class and it still calls the signature with the
base class.

thanks,

Dave Raskin

Nov 17 '05 #4
Hi Dave,

Service doesn't have an overload with a Derived parameter, so the compiler
used a best match that took the overload with the Base parameter. From the
information you've given, I can't tell what SubClass is. However, if you
change the definition of Send(SubClass derivedObject) to this, you could get
what you expect:

public void Send(Derived derivedObject)
{
// send derivedObject
Console.Out.WriteLine("Called public void Send(Derived derivedObject)
signature");
}

Joe
--
http://www.csharp-station.com

"Dave Raskin" <Dave Ra****@discussions.microsoft.com> wrote in message
news:0A**********************************@microsof t.com...
public class Base
{
}

public class Derived : Base
{
}

public class Service
{
public void Send(Base baseObject)
{
// send baseObject
Console.Out.WriteLine("Called public void Send(Base baseObject)
signature");
}

public void Send(Subclass derivedObject)
{
// send derivedObject
Console.Out.WriteLine("Called public void Send(Subclass derivedObject)
signature");
}
}

public class MainClass
{
public static void Main(string[] args)
{
Base baseObject = new Base();
Derived derivedObject = new Derived();

Service service = new Service();

// this calls public void Send(Base baseObject) as expected
service.Send(baseObject);

// this calls public void Send(Base baseObject),
// but it should call public void Send(Subclass derivedObject),
// shouldn't it???
service.Send(derivedObject);
}
}

I expect this to work, but I tested it at runtime, verifying that the
instance is of the Derived class and it still calls the signature with the
base class.

thanks,

Dave Raskin

Nov 17 '05 #5
You're right, the second Send() signautre should have Derived as param, not
Subclass.

Thanks for your answer. My case didn't work, although what I presented here
is a simplified situation, which I thought was essentially the same, but may
be I missed something. I will take a look.

"Flip" wrote:
Howdy. I believe I got it to work properly (as you expected) for me.
Here's the code I used (slightly modified to get it to compile). Output at
the end.
//--------------------------------------------------------------start code
using System;

public class Base
{
}

public class Derived : Base
{
}

public class Service
{
public void Send(Base baseObject)
{
// send baseObject
Console.WriteLine("Called public void Send(Base baseObject) signature");
}

public void Send(Derived derivedObject)
{
// send derivedObject
Console.WriteLine("Called public void Send(Subclass derivedObject)
signature");
}
}

public class MainClass
{
public static void Main(string[] args)
{
Base baseObject = new Base();
Derived derivedObject = new Derived();

Service service = new Service();

// this calls public void Send(Base baseObject) as expected
service.Send(baseObject);

// this calls public void Send(Base baseObject),
// but it should call public void Send(Subclass derivedObject),
// shouldn't it???
service.Send(derivedObject);
}
}
//--------------------------------------------------------------end code
And here's the output I see.

C:\temp>basetesting
Called public void Send(Base baseObject) signature
Called public void Send(Subclass derivedObject) signature

C:\temp>

Nov 17 '05 #6
You're right, the second Send() signautre should have Derived as param, not
Subclass.

Thanks for your answer. My case didn't work, although what I presented here
is a simplified situation, which I thought was essentially the same, but may
be I missed something. I will take a look.

"Flip" wrote:
Howdy. I believe I got it to work properly (as you expected) for me.
Here's the code I used (slightly modified to get it to compile). Output at
the end.
//--------------------------------------------------------------start code
using System;

public class Base
{
}

public class Derived : Base
{
}

public class Service
{
public void Send(Base baseObject)
{
// send baseObject
Console.WriteLine("Called public void Send(Base baseObject) signature");
}

public void Send(Derived derivedObject)
{
// send derivedObject
Console.WriteLine("Called public void Send(Subclass derivedObject)
signature");
}
}

public class MainClass
{
public static void Main(string[] args)
{
Base baseObject = new Base();
Derived derivedObject = new Derived();

Service service = new Service();

// this calls public void Send(Base baseObject) as expected
service.Send(baseObject);

// this calls public void Send(Base baseObject),
// but it should call public void Send(Subclass derivedObject),
// shouldn't it???
service.Send(derivedObject);
}
}
//--------------------------------------------------------------end code
And here's the output I see.

C:\temp>basetesting
Called public void Send(Base baseObject) signature
Called public void Send(Subclass derivedObject) signature

C:\temp>

Nov 17 '05 #7
The signature with Subclass should be with Derived, sorry.

"Joe Mayo" wrote:
Hi Dave,

Service doesn't have an overload with a Derived parameter, so the compiler
used a best match that took the overload with the Base parameter. From the
information you've given, I can't tell what SubClass is. However, if you
change the definition of Send(SubClass derivedObject) to this, you could get
what you expect:

public void Send(Derived derivedObject)
{
// send derivedObject
Console.Out.WriteLine("Called public void Send(Derived derivedObject)
signature");
}

Joe
--
http://www.csharp-station.com

"Dave Raskin" <Dave Ra****@discussions.microsoft.com> wrote in message
news:0A**********************************@microsof t.com...
public class Base
{
}

public class Derived : Base
{
}

public class Service
{
public void Send(Base baseObject)
{
// send baseObject
Console.Out.WriteLine("Called public void Send(Base baseObject)
signature");
}

public void Send(Subclass derivedObject)
{
// send derivedObject
Console.Out.WriteLine("Called public void Send(Subclass derivedObject)
signature");
}
}

public class MainClass
{
public static void Main(string[] args)
{
Base baseObject = new Base();
Derived derivedObject = new Derived();

Service service = new Service();

// this calls public void Send(Base baseObject) as expected
service.Send(baseObject);

// this calls public void Send(Base baseObject),
// but it should call public void Send(Subclass derivedObject),
// shouldn't it???
service.Send(derivedObject);
}
}

I expect this to work, but I tested it at runtime, verifying that the
instance is of the Derived class and it still calls the signature with the
base class.

thanks,

Dave Raskin


Nov 17 '05 #8
The signature with Subclass should be with Derived, sorry.

"Joe Mayo" wrote:
Hi Dave,

Service doesn't have an overload with a Derived parameter, so the compiler
used a best match that took the overload with the Base parameter. From the
information you've given, I can't tell what SubClass is. However, if you
change the definition of Send(SubClass derivedObject) to this, you could get
what you expect:

public void Send(Derived derivedObject)
{
// send derivedObject
Console.Out.WriteLine("Called public void Send(Derived derivedObject)
signature");
}

Joe
--
http://www.csharp-station.com

"Dave Raskin" <Dave Ra****@discussions.microsoft.com> wrote in message
news:0A**********************************@microsof t.com...
public class Base
{
}

public class Derived : Base
{
}

public class Service
{
public void Send(Base baseObject)
{
// send baseObject
Console.Out.WriteLine("Called public void Send(Base baseObject)
signature");
}

public void Send(Subclass derivedObject)
{
// send derivedObject
Console.Out.WriteLine("Called public void Send(Subclass derivedObject)
signature");
}
}

public class MainClass
{
public static void Main(string[] args)
{
Base baseObject = new Base();
Derived derivedObject = new Derived();

Service service = new Service();

// this calls public void Send(Base baseObject) as expected
service.Send(baseObject);

// this calls public void Send(Base baseObject),
// but it should call public void Send(Subclass derivedObject),
// shouldn't it???
service.Send(derivedObject);
}
}

I expect this to work, but I tested it at runtime, verifying that the
instance is of the Derived class and it still calls the signature with the
base class.

thanks,

Dave Raskin


Nov 17 '05 #9
Ok, here's an example of where it fails. This has an added wrinkle of another
virtual method - Process().

public abstract class Base
{
protected Service service = new Service();

public abstract void Process();
}

public class BaseDerived : Base
{
public override void Process()
{
this.service.Send(this);
}
}

public class DerivedDerived : BaseDerived
{
}

public class Service
{
public void Send(Base baseObject)
{
// send baseObject
Console.Out.WriteLine("Called public void Send(Base baseObject)
signature");
}

public void Send(DerivedDerived derivedObject)
{
// send derivedObject
Console.Out.WriteLine("Called public void Send(DerivedDerived
derivedObject) signature");
}
}

public class MainClass
{
public static void Main(string[] args)
{
BaseDerived baseObject = new BaseDerived();
DerivedDerived derivedObject = new DerivedDerived();

Service service = new Service();

// this calls public void Send(Base baseObject) as expected
baseObject.Process();

// this calls public void Send(Base baseObject),
// but it should call public void Send(Subclass derivedObject),
// shouldn't it???
derivedObject.Process();
}
}
Nov 17 '05 #10
Ok, here's an example of where it fails. This has an added wrinkle of another
virtual method - Process().

public abstract class Base
{
protected Service service = new Service();

public abstract void Process();
}

public class BaseDerived : Base
{
public override void Process()
{
this.service.Send(this);
}
}

public class DerivedDerived : BaseDerived
{
}

public class Service
{
public void Send(Base baseObject)
{
// send baseObject
Console.Out.WriteLine("Called public void Send(Base baseObject)
signature");
}

public void Send(DerivedDerived derivedObject)
{
// send derivedObject
Console.Out.WriteLine("Called public void Send(DerivedDerived
derivedObject) signature");
}
}

public class MainClass
{
public static void Main(string[] args)
{
BaseDerived baseObject = new BaseDerived();
DerivedDerived derivedObject = new DerivedDerived();

Service service = new Service();

// this calls public void Send(Base baseObject) as expected
baseObject.Process();

// this calls public void Send(Base baseObject),
// but it should call public void Send(Subclass derivedObject),
// shouldn't it???
derivedObject.Process();
}
}
Nov 17 '05 #11
Dave Raskin <Da********@discussions.microsoft.com> wrote:
Ok, here's an example of where it fails. This has an added wrinkle of another
virtual method - Process().


<snip>

Overload resolution is done at compile time - it works out the
*signature* of which method will be called. Now, the Process method is
calling

this.service.Send(this)

and all it knows about "this" is that it's a BaseDerived - so it
doesn't know it can call Send(DerivedDerived).

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #12
Dave Raskin <Da********@discussions.microsoft.com> wrote:
Ok, here's an example of where it fails. This has an added wrinkle of another
virtual method - Process().


<snip>

Overload resolution is done at compile time - it works out the
*signature* of which method will be called. Now, the Process method is
calling

this.service.Send(this)

and all it knows about "this" is that it's a BaseDerived - so it
doesn't know it can call Send(DerivedDerived).

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

Here's a simpler method to demonstrate the same phenomenon:

public class Base { ... }
public class Derived : Base { ... }
public class Main
{
private void Print(Base b) { Console.Writeline("Base"); }
private void Print(Derived d) { Console.Writeline("Derived"); }

public static void Main(string[] argv)
{
Derived d = new Derived();
Print(d); // Prints "Derived"
Print((Base)d); // Prints "Base", even though d is an instance
of Derived
}
}

Nov 17 '05 #14
Hmm, ok. is true in Java as well? It still seems like it should resolve it at
runtime, but I am not a compiler guy, so what do I know?

Thanks for the clarification!

daver

"Jon Skeet [C# MVP]" wrote:
Dave Raskin <Da********@discussions.microsoft.com> wrote:
Ok, here's an example of where it fails. This has an added wrinkle of another
virtual method - Process().


<snip>

Overload resolution is done at compile time - it works out the
*signature* of which method will be called. Now, the Process method is
calling

this.service.Send(this)

and all it knows about "this" is that it's a BaseDerived - so it
doesn't know it can call Send(DerivedDerived).

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

Nov 17 '05 #15
Bruce,

This seems like a flip of my example. Here you have a Derived type at
compile time and explicitely casting to the Base type. In my case, at compile
time it only knows about the Base type.

daver

"Bruce Wood" wrote:
Jon is right.

Here's a simpler method to demonstrate the same phenomenon:

public class Base { ... }
public class Derived : Base { ... }
public class Main
{
private void Print(Base b) { Console.Writeline("Base"); }
private void Print(Derived d) { Console.Writeline("Derived"); }

public static void Main(string[] argv)
{
Derived d = new Derived();
Print(d); // Prints "Derived"
Print((Base)d); // Prints "Base", even though d is an instance
of Derived
}
}

Nov 17 '05 #16
Yes, but it illustrates the same thing: the run-time type of the
instantiated object isn't what determines which method signature to
call. The compiler decides which method signature to invoke.

Nov 17 '05 #17
Yes, Java is the same. I believe that C++ is also the same.

The rule goes liket his:

The method signature is determined at compile time. That is, if a
method has several different versions with different parameter lists,
the compile-type type of the value passed to the method determines the
signature chosen.

The method overload is determined at run time. That is, if a particular
signature of a particular method is overloaded in a child class, then
whether the base class method or the child class method is to be called
is determined at run time.

(So, just because the compiler determines the signature to call,
_doesn't_ mean that it has decided whether to call the base or derived
implementation of that method. If the derived class overloads the
method, then the choice between the two methods is made at run time.

Nov 17 '05 #18
Rats. I screwed up the use of the term "overload" again. :(

Overload resolution is done at compile time: "overload" refers to
methods with the same name but different signatures.

Override resolution is done at run time: "override" refers to methods
with the same name and the same signature defined at different levels
of the class hierarchy.

Nov 17 '05 #19
Right, got it, makes sense now. I was wrong all this time, go figure ;-)

daver

"Bruce Wood" wrote:
Rats. I screwed up the use of the term "overload" again. :(

Overload resolution is done at compile time: "overload" refers to
methods with the same name but different signatures.

Override resolution is done at run time: "override" refers to methods
with the same name and the same signature defined at different levels
of the class hierarchy.

Nov 17 '05 #20

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.