Problem with virtual method

J

Jon Davis

If I have a class with a virtual method, and a child class that overrides
the virtual method, and then I create an instance of the child class AS A
base class...

BaseClass bc = new ChildClass();

.... and then call the virtual method, why is it that the base class's method
is called instead of the overridden method? How do I fix this if I don't
know at runtime what the child class is? I'm using
Activator.CreateInstance() to load the child class from a satellite DLL, a
third-party plug-in that inherits my base class, so I therefore cannot
declare the child class type in the code or at compile time.

Thanks,
Jon
 
J

Jon Davis

But did you try it with a satellite DLL instantiated with
Activator.CreateInstance()?

Otherwise we're just proving the difference between an overridden virtual
method and the "new" keyword, that overriding works.

Honest to God, though, my child class in an another DLL is overriding my
virtual method, and the base virtual method is being called. I'm stepping
through the code, and the base class comes up in the code window on that
method. It is definitely marked as "virtual". The child class is definitely
a child (public class MyChild : MyBase), and the method definitely has the
"override" keyword.

This has had me stumped for at least a week, and I CANNOT afford to lose
another day on this project!! I MUST move on! But this plug-in feature is
one of the core highlights of the product.

What the hell is going on?? :( :(

Jon
 
J

Jon Skeet

Jon Davis said:
If I have a class with a virtual method, and a child class that overrides
the virtual method, and then I create an instance of the child class AS A
base class...

BaseClass bc = new ChildClass();

... and then call the virtual method, why is it that the base class's method
is called instead of the overridden method? How do I fix this if I don't
know at runtime what the child class is? I'm using
Activator.CreateInstance() to load the child class from a satellite DLL, a
third-party plug-in that inherits my base class, so I therefore cannot
declare the child class type in the code or at compile time.

I suspect you haven't overridden the method properly. Could you post a
short but complete example which demonstrates the problem? See
http://www.pobox.com/~skeet/csharp/complete.html for what I mean.
 
J

Jon Davis

I suspect you haven't overridden the method properly. Could you post a
short but complete example which demonstrates the problem? See
http://www.pobox.com/~skeet/csharp/complete.html for what I mean.

You already said this and gave that link in a prior thread. No I can't because I don't know how to reproduce the problem without displaying all of my code.

Here's exactly what I have, with class, instance, and object names changed for the group:

IN ASSEMBLY A:

// name changed for group
public abstract class MyType {

...

// THIS IS WHERE THE DEBUGGER GOES WHEN STEPPING THROUGH THE CODE
// name, return type name changed for group
public virtual MyResultType MyMethod( ... ) {

.. default output ..

}

}

// name changed for group
public class MyCallingType {

// name, return type name changed for group
public MyResultType[] MyActions( ... ) {

...

// type names, names changed for group
MyTypeInstanceList myTypeInstances = Thing.MyLoadedExternalPlugIns;

...

for (int i=0; i<myTypeInstances.Count; i++) {



// type name, name changed for group
MyType myTypeInstance = myTypeInstances;

// NOTE THAT AT THIS POINT THE DEBUGGER
// SAYS THAT THIS IS A MyNewType (see below)

...

// type name changed for group
MyResultType pr;

...

pr = myType.MyMethod( ... );

...


}

}
}


IN ASSEMBLY B:

// names changed for group
public class MyNewType : MyType {

...

// THIS IS WHERE THE DEBUGGER SHOULD BE GOING
// WHEN STEPPING THROUGH THE CODE
// name, return type name changed for group
public override MyResultType MyMethod( ... ) {

...

}

}



Jon
 
J

Jon Davis

This is how I'm instantiating the customized type ("MyNewType") from Assembly B...

assem = System.Reflection.Assembly.LoadFile(fn);

....

Type t = assem.GetType(clrName);

....

MyTypeDescriptor ptd = new MyTypeDescriptor(t, vers, name, desc, longDesc);

....

typeInstance = (MyType)Activator.CreateInstance(
ptd.Type, new object[] {thing, myTypeNode});


Jon
(Ignore previous [cancelled] reply...)


Jon Skeet said:
I suspect you haven't overridden the method properly. Could you post a
short but complete example which demonstrates the problem? See
http://www.pobox.com/~skeet/csharp/complete.html for what I mean.
You already said this and gave that link in a prior thread. No I can't because I don't know how to reproduce the problem without displaying all of my code.

Here's exactly what I have, with class, instance, and object names changed for the group:

IN ASSEMBLY A:

// name changed for group
public abstract class MyType {

...

// THIS IS WHERE THE DEBUGGER GOES WHEN STEPPING THROUGH THE CODE
// name, return type name changed for group
public virtual MyResultType MyMethod( ... ) {

.. default output ..

}

}

// name changed for group
public class MyCallingType {

// name, return type name changed for group
public MyResultType[] MyActions( ... ) {

...

// type names, names changed for group
MyTypeInstanceList myTypeInstances = Thing.MyLoadedExternalPlugIns;

...

for (int i=0; i<myTypeInstances.Count; i++) {



// type name, name changed for group
MyType myTypeInstance = myTypeInstances;

// NOTE THAT AT THIS POINT THE DEBUGGER
// SAYS THAT THIS IS A MyNewType (see below)

...

// type name changed for group
MyResultType pr;

...

pr = myTypeInstance.MyMethod( ... );

...


}

}
}


IN ASSEMBLY B:

// names changed for group
public class MyNewType : MyType {

...

// THIS IS WHERE THE DEBUGGER SHOULD BE GOING
// WHEN STEPPING THROUGH THE CODE
// name, return type name changed for group
public override MyResultType MyMethod( ... ) {

...

}

}



Jon
 
J

Jon Skeet

Jon Davis said:
(Ignore previous [cancelled] reply...)

Too late - but see my reply to it.
// THIS IS WHERE THE DEBUGGER GOES WHEN STEPPING THROUGH THE CODE

Have you tried running the code in release mode? Maybe it's just a
debugger bug.
 
J

Jon Skeet

Jon Davis said:
This is how I'm instantiating the customized type ("MyNewType")
from Assembly B...

That doesn't really help me until I can run the code. I've managed to
whip up a version which *does* work (see another post) - find out the
differences between that and your code. There's really nothing else I
can do without actually having some of your code in a form I can
compile and run directly.
 
J

Jon Skeet

Jon Davis said:
Ah, a helpful, insightful answer that doesn't involve your copy-pasting into
the debugger (which I can do)!

Actually, this answer made me realize that files were not being properly
propogated to the proper directories upon compile. Hopefully that's my
problem, still testing ...

(As I said, there was no more source code to demonstrate my problem. ;)

But there was - if you'd posted a short but complete example which
*wasn't* working on your box, I could have tried it and said whether or
not it worked on *my* box. We'd then have seen that the code worked on
one machine and not another, and that therefore it probably wasn't the
code that was the problem, but the manner of running it.

It's absolutely *crucial* that everyone ends up looking at the same
code in this kind of thing.
 
J

Jon Davis

Jon Skeet said:
But there was - if you'd posted a short but complete example which
*wasn't* working on your box,

But see I couldn't do that without giving you everything. I have ten
projects all outputting to the same directory, and I didn't realize that
this was the problem.

There was absolutely no way to help you help me by reproducing sample code
in new project code because I wouldn't have repeated the same error (unless
per chance I actually caught myself along the way).

Thanks again for your insightful question (re your previous post, "Release
mode"), it actually really helped me drill down to the problem, and frankly
I don't know how else I would have found my error.

Jon
 
J

Jon Skeet

Jon Davis said:
But see I couldn't do that without giving you everything.

But you could. You could have reduced the code gradually (a copy of the
code, rather) until it worked. That would actually have shown you the
error very quickly (see below) due to what the problem turned out to
be. If the problem *had* been in the code, however, you would then have
found it when it went from "not working" to "working". Either way,
you'd have found the problem in the end.
There was absolutely no way to help you help me by reproducing sample code
in new project code because I wouldn't have repeated the same error (unless
per chance I actually caught myself along the way).

Which you should have done, because immediately after copying the full
code, the first thing to do would be to test that it still didn't work.
Thanks again for your insightful question (re your previous post, "Release
mode"), it actually really helped me drill down to the problem, and frankly
I don't know how else I would have found my error.

See above.
 
J

Jon Davis

Jon Davis said:
Ah, a helpful, insightful answer that doesn't involve your copy-pasting into
the debugger (which I can do)!

Actually, this answer made me realize that files were not being properly
propogated to the proper directories upon compile. Hopefully that's my
problem, still testing ...

Hmm, nope, this wasn't the problem. The problem remains.

... Time to find other resources ..
 
J

Jon Davis

Jon, it took me about half an hour to hand-pick the relevant lines of code
that would be useful to you. You are insistent on not visually evaluating
what I wrote, which is your prerogative.

Developing sample code that reproduces the problem is only possible if you
know how to reproduce the problem, and I don't know how to reproduce the
problem. Obviously if someone in this group cannot help me drill down to the
problem with the information I provided and without a full reproduction,
then, in order to provide a reproduction of the problem, I will have to
rewrite from the ground up, adding line by line what I've done, until I
discover the culprit (hence, I find what makes it reproduceable). But that
will take days, and by the time I find the culprit I won't need this
newsgroup.

Thanks anyway.

Jon
 
J

Jon Davis

I should point out that my project is not currently open source and as such
it is private. I am not going to post the entire project nor link to it, it
would be a waste of your time anyway (Mr. Skeet).

I should also point out that I cannot simply remove code until the problem
fixes itself.

1. I don't know what to delete.
2. If I do delete anything, it will break the entire project.
3. I cannot simply paste the code into a new project because there are far
too many interdependent classes and types and methods, etc.

Finally, I should point out that, while we must try to be respectful to
those who help, those who help should be respectful of these (above)
hindrances. I've done the best I can to provide what I know without posting
a link to the entire solution in a .zip file, short of rewriting code from
scratch on this matter, which, as I said, will negate the usefulness of this
group.

Seems I have no choice, which is fine. Nobody owes me anything.

Thanks again for the willingness to try to help. Please put your tired self
to rest.

Jon


Jon Davis said:
Jon, it took me about half an hour to hand-pick the relevant lines of code
that would be useful to you. You are insistent on not visually evaluating
what I wrote, which is your prerogative.

Developing sample code that reproduces the problem is only possible if you
know how to reproduce the problem, and I don't know how to reproduce the
problem. Obviously if someone in this group cannot help me drill down to the
problem with the information I provided and without a full reproduction,
then, in order to provide a reproduction of the problem, I will have to
rewrite from the ground up, adding line by line what I've done, until I
discover the culprit (hence, I find what makes it reproduceable). But that
will take days, and by the time I find the culprit I won't need this
newsgroup.

Thanks anyway.

Jon
 
J

Jay B. Harlow [MVP - Outlook]

Jon,
Go the other direction!

Start a new solution with two projects. The first project loads the second
project and calls the virtual method. Include the minimalist amount of code
to demonstrate the feature. Does it work?

Start adding features from your larger project, until this new project
fails. Baby steps! Add things one at a time. Hopefully when you added X, it
fails, then you know to look at X in the larger project.

This helps solves two problems.
1. It gives you a reference point to compare to the larger project.
2. It proves what you are attempting to do works, or doesn't work. Without
being bothered by the shear volume of the rest of your main project.

3. It also provides a small project that fails, which is what Jon Skeet was
asking for.

Hope this helps
Jay

Jon Davis said:
I should point out that my project is not currently open source and as such
it is private. I am not going to post the entire project nor link to it, it
would be a waste of your time anyway (Mr. Skeet).

I should also point out that I cannot simply remove code until the problem
fixes itself.

1. I don't know what to delete.
2. If I do delete anything, it will break the entire project.
3. I cannot simply paste the code into a new project because there are far
too many interdependent classes and types and methods, etc.

Finally, I should point out that, while we must try to be respectful to
those who help, those who help should be respectful of these (above)
hindrances. I've done the best I can to provide what I know without posting
a link to the entire solution in a .zip file, short of rewriting code from
scratch on this matter, which, as I said, will negate the usefulness of this
group.

Seems I have no choice, which is fine. Nobody owes me anything.

Thanks again for the willingness to try to help. Please put your tired self
to rest.

Jon
 
J

Jon Davis

Thanks for the feedback, Jay, I'll consider your advice. And thanks for not
beating me over the head like some other people have done in the past for
not doing things their way.

Jon
 
G

gerry

JonD - take some advice - add the skeeter to your ignore list.


Jon Davis said:
I should point out that my project is not currently open source and as such
it is private. I am not going to post the entire project nor link to it, it
would be a waste of your time anyway (Mr. Skeet).

I should also point out that I cannot simply remove code until the problem
fixes itself.

1. I don't know what to delete.
2. If I do delete anything, it will break the entire project.
3. I cannot simply paste the code into a new project because there are far
too many interdependent classes and types and methods, etc.

Finally, I should point out that, while we must try to be respectful to
those who help, those who help should be respectful of these (above)
hindrances. I've done the best I can to provide what I know without posting
a link to the entire solution in a .zip file, short of rewriting code from
scratch on this matter, which, as I said, will negate the usefulness of this
group.

Seems I have no choice, which is fine. Nobody owes me anything.

Thanks again for the willingness to try to help. Please put your tired self
to rest.

Jon
 
J

Jon Skeet

[I realise you won't even see this if you really have added me to your
killfile. Shame, but there we go.]

Jon Davis said:
QUESTION: What on EARTH would disable the virtualness of a virtual method
except something (??) among the few lines of code that I posted?

I don't know - but until I can see it failing on my own box, I'll be as
baffled as you are.
There is NO WAY that the other code, the business rules, which has NOTHING
to do with virtualness of the method, has anything to do with this problem.
This IS a bug in the Framework.

It's possible - but I've seen that kind of certainty end up being
misplaced far too often to just believe it on your word, I'm afraid.
I have decided to make the method abstract.

If it works, that's great :)

If you still have a copy of the failing project, large as it is, I'd be
fascinated to have a look at it. I realise it's private - I'm happy to
sign any NDAs etc. If it *is* a bug in the framework, it's pretty
important to get it looked at - and I'm confident that I *would* be
able to get rid of a lot of the business logic to get a small working
(or rather failing) example given the whole thing.
 
J

Jon Davis

Okay, making it abstract did help me identify that this was an assembly
loading problem. I have fixed the assembly loading problem and the problem
is resolved--the child class is FINALLY being executed, even after reverting
back to virtual (YAAAAY!!).

I still perceive this to be a flaw in the Framework. There should have been
an error output indicating that the assembly did not load correctly. QUITE
UNACCEPTABLE, Microsoft. I wasted at least two weeks on this.

Jon
 
J

Jon Davis

Jon Davis said:
Hmm, nope, this wasn't the problem. The problem remains.

.. Time to find other resources ..

Okay, making it abstract did help me identify that this was an assembly
loading problem. I have fixed the assembly loading problem and the problem
is resolved--the child class is FINALLY being executed, even after reverting
back to virtual (YAAAAY!!).

I still perceive this to be a flaw in the Framework. There should have been
an error output indicating that the assembly did not load correctly. QUITE
UNACCEPTABLE, Microsoft. I wasted at least two weeks on this.

Jon
 

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