Gamma said:
Thank you for your help.
1. What I want to do is this: I have an array of processes, and I want
to put them in a listbox. Since the listbox uses the "ToString" method
to display the process's name, and since the "ToString" method of the
Process's class (System.Diagnostics.Process) returns the class's name
besides the name of the process (which is redundant information), I
inherited a class NewProcess that overrides only the "ToString" method.
Then you need to actually create instances of NewProcess, not instances of
Process. If you are not creating the instances of the Process yourself, you
will need to wrap them as Martin suggests, since you can't go back and
change something created as a Process into a NewProcess.
If you ARE creating the instances, then the change sloan offered will work
fine. In that case, you can ensure that the instance created is of the
derived class you've defined, rather than the base class, and the override
will work just fine.
2. My roots are C++, and in C++, if I have a class that inherits from
another class and overrides a method, the correct way to use it is in
the following way (C++ code):
Process *p,*n;
p = new Process;
DoSomething(p);
n = (MyProcess*)p;
while trying to learn C#, I used that same technique, but obviously not
successfully.
I agree with Martin. It's true that a C++ compiler will let you do this.
But that doesn't make it correct code (and if you did a C++ safe typecast
like that, it would fail), nor does it do what you seem to think it does.
A true "override" of behavior involves virtual functions in C++. Without a
virtual function, the behavior is defined only by the type the pointer is
currently treated as.
For example:
class A
{
public:
int Value { return 5; }
}
class B : public A
{
public:
int Value { return 10; }
}
If you have this code:
A *a1, *a2;
B *b1;
a1 = new A();
a2 = (B *)a1;
b1 = (B *)a1;
Then a1->Value() returns 5. a2->Value() *also* returns 5. The statement
b1->Value() returns 10, but only because you're calling the function
B::Value explicitly. It has nothing to do with the actual instance a1 and
if you cast b1 back to a pointer to an A, you are back to the call to
Value() returning 5.
If all you're inheriting the class for is to return a different value when
you explicitly call B::Value(), you might as well skip the inheritance and
just hard-code your constant instead where it would have been used.
More commonly, when one talks about an "override", they mean that the class
will retain the overridden behavior even when the class is only known to be
a parent class. For example:
class A
{
public:
virtual int Value { return 5; }
}
class B : public A
{
public:
virtual int Value { return 10; }
}
In this case, if you have this code:
A *a1;
B *b1;
a1 = new A();
b1 = (B *) a1;
b1 = new B();
a1 = (A *) b1;
After the first two lines have executed, a1->Value() would return 5, as
would b1->Value(). After the third line has executed, b1->Value() would
return 10, and after the fourth line executes, a1->Value() would also return
10.
In other words, in this second example the value returned depends not on the
type of the variable, but on the type used when creating the instance of the
class.
Note that in both examples, casting something created as an A to a pointer
to a B is *illegal*. It doesn't harm anything in this case (as in the
second line of code executed), because no attempt is made to access
something that was defined only in the B class. But if the B class included
some member variable or a virtual function, either of which didn't exist in
the A class, you would get an error trying to access that part of the B
class through a pointer caSt from an instance of an A class (the exact error
would vary...it could just be simply the wrong data, or the program could
crash, depending on what you tried to access and where the object was in
memory).
In other words, the code you posted is really dangerous, and doesn't at all
do what you want. It didn't work in C++ and it doesn't work in C#.
Thankfully, C# is better about protecting you, and thus generates the error
you're getting.
Therefore, what I want to understand is this: I have a
Process object (which is a given situation), and I want to
polymorphically use it as my derived class (to force it to treat it's
data the way I want it to).
You can't force something that's not already a NewProcess to act as if it is
a NewProcess.
Pete