• Want to receive the latest contracting news and advice straight to your inbox? Sign up to the ContractorUK newsletter here. Every sign up will also be entered into a draw to WIN £100 Amazon vouchers!

.NET overloads/shadows

ASB

Godlike
Thanks received
91
Ok, so a base class has a method in it. It's not virtual. A derived class needs a slightly different implementation. Can't override because it's not virtual. VB tells one to declare it overloads. Run everything up, in the debugger it's fine. The overload is called.

But, the binding is actually done at compile time. This gives rise to:-

- Deploy the assembly with the derived class. No changes to behaviour. The method in the base class is still called.

- Recompile the client code. Deploy it. No changes other than compilation. The method in the derived class is now called.

I accept this happens, and why it happens (call not callvirt). But surely there are no circumstances in which it can be though of as correct. Why does the compiler allow a method to be overloads/shadows when it is not going to call it until the client is recompiled.

[/rant]
 
Hrm,

That doesn't sound right. I've had a derived class with an overloaded method call correctly without having to recompile the client code. Are you sure the reference is pulling from the correct place, and its not running from a version in the GAC?
 
Hrm,

That doesn't sound right. I've had a derived class with an overloaded method call correctly without having to recompile the client code. Are you sure the reference is pulling from the correct place, and its not running from a version in the GAC?

Absolutely sure (but that doesn't make me right!).

Obviously it's not possible to reproduce it in the IDE without twiddling build setting etc. Heres how to do it (for the terminally bored).

- Create a baseclass with a "SomeMethod" returning "from base".
- Create a derived class
- Create a client, instance derived class and write result or some method to console

Copy exe and dll somewhere convenient.
Run it.

- Now update the derived class to overload the method returning "from derived"
- Copy new derived class
- Run and watch in amazement as it fails to call the overload. [Or laugh at my expense of course]

Recompile the client and now it will call the overload.

Now, maybe this is because it is VB (but I don't think so, it happens with Cobol as well). But it most definitely occurs on my machine which VS2005 SP1.
 
I may have the wrong end of the stick here, but it is how the compiler determines which overload to call when there is some ambiguity.

http://blogs.extremeoptimization.com/jeffrey/archive/2006/02/10/7134.aspx

http://msdn2.microsoft.com/en-us/library/tb18a48w.aspx

There is no ambiguity, it's when the binding actually happens which is the problem.

public class A
Function fx as String
return "from base"
end function
end class

public class B Inherits A
end class

And the client code

sub Main

dim ob as new b
console.write ob.fx

end sub

This is all fine.

Now I change B as

public class B Inherits A
overloads function fx as string
return "From Derived"
end class

Build and deploy B.

Behaviour is unchanged. Oops.

Rebuild the client and it now calls the overload.

So, what I think is happening is that at compile time the function is resolved as an IL.CALL. Thus it will call whatever was resolved at compile time. Because it is not marked as overridable it is not producing a CALLVIRT.

When the client is recompiled it resolves to the overload in the derived class. Again with an IL CALL.

It seems to me that Overloads - of a base class method - should not be allowed when the base class method is not virtual. Because this is going to break existing clients. [Unfortunately in VB at least the compiler demand you overload it].

To be fair, you'll never see the the problem in testing. Only in partial deployment.
 
Don't know about VB, or .NET for that matter, but how else is going to work? If it's not virtual it means it's a straight function call, and when the function doesn't exist in B it's a straight call to the one in A. It can't know in advance that you're going to do something different later.

You're expecting the compiler to insert some extra code to look for a derived version at runtime, which is exactly what happens with virtual functions.

So the answer is a) use virtual, or b) deploy the things that need to be deployed.

It's perfectly okay for this to be allowed; it would never be a problem in a single EXE or DLL. It's only because you're trying to combine one half of the program with another half from a previous build, and haven't designed it to allow that.
 
Hrm,

In C#, i'd change the overloads to new. I'll give this a go when I get some time and see what happens. I've got a funny feeling I've run across this before, just have to remember what i changed
 
C#

C#

You are talking about overloads (same method name, different parameters) or overrides (same method signature, but replacing the definition in a base class).

Everyone seems to be mixing overloads and overrides and I ain't got a clue what's going on.

It didn't help that I downed 10 pints last night and got about 4 hours sleep either. :ohwell
 
Don't know about VB, or .NET for that matter, but how else is going to work? If it's not virtual it means it's a straight function call, and when the function doesn't exist in B it's a straight call to the one in A. It can't know in advance that you're going to do something different later.

You're expecting the compiler to insert some extra code to look for a derived version at runtime, which is exactly what happens with virtual functions.

So the answer is a) use virtual, or b) deploy the things that need to be deployed.

It's perfectly okay for this to be allowed; it would never be a problem in a single EXE or DLL. It's only because you're trying to combine one half of the program with another half from a previous build, and haven't designed it to allow that.

Well, I wouldn't argue with much of that. Except for "and when the function doesn't exist in B". Since the client is calling B.Something I don't think it is entirely unreasonable to expect B.Something to be called.
 
You are talking about overloads (same method name, different parameters) or overrides (same method signature, but replacing the definition in a base class).

Everyone seems to be mixing overloads and overrides and I ain't got a clue what's going on.

It didn't help that I downed 10 pints last night and got about 4 hours sleep either. :ohwell

To paraphrase VectraMan I'm cheating and been bitten.

It's an overload with the same parameters (equivalent to "new" I think in C#). [I guess the fundamental problem is being allowed to overload a method in a base class with a method in a derived class with an identical signature]
 

Advertisers

Back
Top