Connecting Tech Pros Worldwide Help | Site Map

Accessing members which have been hidden by "new"

Robert Fuchs
Guest
 
Posts: n/a
#1: Jun 27 '08
Hello,

This example:

public class BaseC
{
public int x;
public void Invoke() {}
}
public class DerivedC : BaseC
{
new public void Invoke() {}
}

is from here: http://msdn2.microsoft.com/en-us/library/435f1dw2.aspx
I can access the original (hidden) method Invoke() by using BaseC.Invoke().

Now look at this:

public class BaseC
{
public int x;
public void Invoke() {}
}

public class DerivedC : BaseC
{
public int y;
}

public class DerivedDerivedC : DerivedC
{
public int z;
new public void Invoke() {}
}

How do I access the original (hidden) method ?

BaseC.Invoke() doesn't work? Why?

regards, Robert

Peter Duniho
Guest
 
Posts: n/a
#2: Jun 27 '08

re: Accessing members which have been hidden by "new"


On Mon, 21 Apr 2008 15:34:04 -0700, Robert Fuchs <nix@nix.atwrote:
Quote:
public class BaseC {
public int x;
public void Invoke() {}
}
public class DerivedC : BaseC
{
new public void Invoke() {}
}
>
is from here: http://msdn2.microsoft.com/en-us/library/435f1dw2.aspx
I can access the original (hidden) method Invoke() by using
BaseC.Invoke().
Do you mean "base.Invoke()", as from within an instance method for
example? "BaseC.Invoke()" would imply a static method, and "Invoke()" is
not in this case a static method.
Quote:
Now look at this:
>
public class BaseC {
public int x;
public void Invoke() {}
}
>
public class DerivedC : BaseC
{
public int y;
}
>
public class DerivedDerivedC : DerivedC
{
public int z; new public void Invoke() {}
}
>
How do I access the original (hidden) method ?
>
BaseC.Invoke() doesn't work? Why?
Again, do you mean "base.Invoke()"?

If so, then you can't because the immediate base class has no such
method. However, you can cast your instance to BaseC and access the
method that way.

That said, it's almost always a mistake to hide a class member anyway.
It's very easy for code to fail to operate correctly or as expected when
you do so, because the base classes won't necessarily have any way to know
about or use the hidden method.

Pete
Robert Fuchs
Guest
 
Posts: n/a
#3: Jun 27 '08

re: Accessing members which have been hidden by "new"


If so, then you can't because the immediate base class has no such
Quote:
method. However, you can cast your instance to BaseC and access the
method that way.
I also thought about casting would do the trick:
((BaseClass)this).MyMethod();
But I have another problem: MyMethod() is protected, and I don't want to
change that.

So I get the error message:
"Cannot access protected member 'member' via a qualifier of type 'type1';
the qualifier must be of type 'type2' (or derived from it)"

Any idea?

regards, Robert

Jeroen Mostert
Guest
 
Posts: n/a
#4: Jun 27 '08

re: Accessing members which have been hidden by "new"


Peter Duniho wrote:
Quote:
On Mon, 21 Apr 2008 15:34:04 -0700, Robert Fuchs <nix@nix.atwrote:
Quote:
>Now look at this:
>>
>public class BaseC {
> public int x;
> public void Invoke() {}
>}
>>
>public class DerivedC : BaseC
>{
> public int y;
>}
>>
>public class DerivedDerivedC : DerivedC
>{
> public int z; new public void Invoke() {}
>}
>>
>How do I access the original (hidden) method ?
>>
>BaseC.Invoke() doesn't work? Why?
>
Again, do you mean "base.Invoke()"?
>
If so, then you can't because the immediate base class has no such
method.
Yes it does, properly inherited from BaseC, and base.Invoke() is just going
to work.

--
J.
http://symbolsprose.blogspot.com
John B
Guest
 
Posts: n/a
#5: Jun 27 '08

re: Accessing members which have been hidden by "new"


Peter Duniho wrote:
<...>
Quote:
That said, it's almost always a mistake to hide a class member anyway.
It's very easy for code to fail to operate correctly or as expected when
you do so, because the base classes won't necessarily have any way to
know about or use the hidden method.

Whilst I agree to a point that it's _almost_ always a mistake to hide a
member.
A common pattern I use is with generics.
Say I have:
abstract class Fu
{
public virtual object Value
{
get { return ValueInternal; }
}
protected abstract object ValueInternal{get;}
}

class Bar<T: Fu
{
public new T Value
{
get { return m_Value; }
set { m_Value = value; }
}
protected override object ValueInternal
{
get { return Value; }
}
}
This obviously allows both strong typed functionality with generics and
easy polymorphism with the base non-generic class.

(Yes I know you said _almost_, just wanted to point out a valid reason)

JB
Peter Duniho
Guest
 
Posts: n/a
#6: Jun 27 '08

re: Accessing members which have been hidden by "new"


On Mon, 21 Apr 2008 16:39:59 -0700, Robert Fuchs <nix@nix.atwrote:
Quote:
Quote:
>If so, then you can't because the immediate base class has no such
>method. However, you can cast your instance to BaseC and access the
>method that way.
>
I also thought about casting would do the trick:
((BaseClass)this).MyMethod();
But I have another problem: MyMethod() is protected, and I don't want to
change that.
>
So I get the error message:
"Cannot access protected member 'member' via a qualifier of type
'type1'; the qualifier must be of type 'type2' (or derived from it)"
Interesting. I admit, I didn't anticipate that. It looks to me as though
protected members are defined as private with respect to use through their
defining type, accessible implicitly only when visible through inheritance.

I find it a little weird, actually, because it means you can only call
hidden protected methods from within the instance of the deriving class,
while you can call any protected method from any instance.

For example:

class A
{
protected void MethodA() { Console.WriteLine("A.MethodA"); }
protected void MethodC() { Console.WriteLine("A.MethodC"); }
}

class B : A
{
}

class C : B
{
new protected void MethodA() { Console.WriteLine("C.MethodA");
}

public void MethodB()
{
C c = new C();

base.MethodA(); // this works
c.MethodC(); // this works
// ((A)this).MethodA(); // this doesn't
// ((A)c).MethodA(); // this doesn't
}
}
Quote:
Any idea?
Well, I admit...my previous reply made an assumption, which Jeroen pointed
out was wrong. That is, I assumed that you had actually tried using the
"base." notation and that had failed. Obviously you hadn't, because it
does work and as near as I can tell does just what you want it to.

Pete
Peter Duniho
Guest
 
Posts: n/a
#7: Jun 27 '08

re: Accessing members which have been hidden by "new"


On Mon, 21 Apr 2008 18:10:22 -0700, John B <jbngspam@yahoo.comwrote:
Quote:
Whilst I agree to a point that it's _almost_ always a mistake to hide a
member.
A common pattern I use is with generics.
Say I have:
abstract class Fu
{
public virtual object Value
{
get { return ValueInternal; }
}
protected abstract object ValueInternal{get;}
}
>
class Bar<T: Fu
{
public new T Value
{
get { return m_Value; }
set { m_Value = value; }
}
protected override object ValueInternal
{
get { return Value; }
}
}
This obviously allows both strong typed functionality with generics and
easy polymorphism with the base non-generic class.
Well, I'd say that once you allow the polymorphism with the base
non-generic class, you've lost the main advantage of using generics. That
is, you no longer have compile-time type checking for instances of that
class. Why bother with a derived generic in that case?

I also don't understand the point of making the base property virtual, if
you're just going to hide it anyway. Who's going to override it?

If one _is_ going that route, I'd say you might as well just use a
different name for the typed (generic) form of the property. Like
"TypedValue" or something like that. You'll still want to override the
base Value property, but then at least there'd be a point to having the
base class property be "virtual" and the code wouldn't seem so circular.
:)

Obviously I won't go so far as to say hiding a member is _never_ the right
thing to do, but I don't agree that your example is proof of that. :)
It's my opinion that there are better ways to approach a situation like
that.

Pete
John B
Guest
 
Posts: n/a
#8: Jun 27 '08

re: Accessing members which have been hidden by "new"


Peter Duniho wrote:
Quote:
On Mon, 21 Apr 2008 18:10:22 -0700, John B <jbngspam@yahoo.comwrote:
>
Quote:
>Whilst I agree to a point that it's _almost_ always a mistake to hide
>a member.
>A common pattern I use is with generics.
>Say I have:
>abstract class Fu
>{
> public virtual object Value
> {
> get { return ValueInternal; }
> }
> protected abstract object ValueInternal{get;}
>}
>>
>class Bar<T: Fu
>{
> public new T Value
> {
> get { return m_Value; }
> set { m_Value = value; }
> }
> protected override object ValueInternal
> {
> get { return Value; }
> }
>}
>This obviously allows both strong typed functionality with generics
>and easy polymorphism with the base non-generic class.
>
Well, I'd say that once you allow the polymorphism with the base
non-generic class, you've lost the main advantage of using generics.
That is, you no longer have compile-time type checking for instances of
that class. Why bother with a derived generic in that case?
>
In one place I have used this pattern is where I have a base class I use
for reporting criteria.
I have a form that can add/edit/remove criteria and only knows about the
base class.
I use this base form for many report types and only the list of
available criteria changes.
One of the generic parameters (there are 2) denotes the "Field" which is
being targeted by the criteria (ie customer surname) which is redefined
in the generic class from object to <Fand in the "real" concrete class
to an enum type and returns the actual enum item the criteria is targetting.
In the concrete report forms, the criteria are then treated as their
"real" types.

An example is below my signature.

Its kind of hard to explain without an example but the "example" is not
easily extracted out of the whole application.
Quote:
I also don't understand the point of making the base property virtual,
if you're just going to hide it anyway. Who's going to override it?
>
True, just habit of making all members virtual in abstract classes
(unless specifically necessary not to).
Quote:
If one _is_ going that route, I'd say you might as well just use a
different name for the typed (generic) form of the property. Like
"TypedValue" or something like that. You'll still want to override the
base Value property, but then at least there'd be a point to having the
base class property be "virtual" and the code wouldn't seem so
circular. :)
>
Fair comment, I'm not really a fan though of this though, as I would
automatically type instance.Value which would then bite me as I'd get a
compile error saying ...object cant be converted to X and i'd have to
change it to instance.TypedValue so I'd have to remember to always use
TypedValue.
Quote:
Obviously I won't go so far as to say hiding a member is _never_ the
right thing to do, but I don't agree that your example is proof of
that. :) It's my opinion that there are better ways to approach a
situation like that.
>
Quite possible that there are better ways than this. Unfortunately I'm
the only input on this so that limits me to my own ideas :)

JB

enum CustomerFields
{
Surname = 1,
FirstName,
Postcode,
}

abstract class Criteria
{
public object Field { get { return FieldInternal; } }
protected abstract object FieldInternal { get; }
public object Value { get { return ValueInternal; } }
protected abstract object ValueInternal { get; }
}

abstract class Criteria<F: Criteria
{
public abstract new F Field { get; }
protected override object FieldInternal
{
get { return Field; }
}
}

abstract class Criteria<F, V: Criteria<F>
{
V m_Value;

public new V Value
{
get { return m_Value; }
set { m_Value = value; }
}

protected override object ValueInternal
{
get { return Value; }
}
}

class CustomerSurnameCriteria : Criteria<CustomerFields, string>
{
public override CustomerFields Field
{
get { return CustomerFields.Surname; }
}
}
Robert Fuchs
Guest
 
Posts: n/a
#9: Jun 27 '08

re: Accessing members which have been hidden by "new"


>Any idea?
Quote:
>
Well, I admit...my previous reply made an assumption, which Jeroen pointed
out was wrong. That is, I assumed that you had actually tried using the
"base." notation and that had failed. Obviously you hadn't, because it
does work and as near as I can tell does just what you want it to.
No, "base." does not what I want, because the immediate base class has no
such method.
That is exactly the point why I asked.
I would need something like "base.base." ;-)

regards, Robert

Ben Voigt [C++ MVP]
Guest
 
Posts: n/a
#10: Jun 27 '08

re: Accessing members which have been hidden by "new"


Robert Fuchs wrote:
Quote:
Quote:
Quote:
>>Any idea?
>>
>Well, I admit...my previous reply made an assumption, which Jeroen
>pointed out was wrong. That is, I assumed that you had actually
>tried using the "base." notation and that had failed. Obviously you
>hadn't, because it does work and as near as I can tell does just
>what you want it to.
>
No, "base." does not what I want, because the immediate base class
has no such method.
Do you have a test to prove this? Show source, so we know what you're
talking about.

You cannot access a protected method that is hidden in your base class, only
if your own class is the one hiding it. Then it matters not how deep in the
hierarchy the definition was provided.
Quote:
That is exactly the point why I asked.
I would need something like "base.base." ;-)
>
regards, Robert

Peter Duniho
Guest
 
Posts: n/a
#11: Jun 27 '08

re: Accessing members which have been hidden by "new"


On Wed, 23 Apr 2008 04:54:49 -0700, Robert Fuchs <nix@nix.atwrote:
Quote:
Quote:
Quote:
>>Any idea?
>>
>Well, I admit...my previous reply made an assumption, which Jeroen
>pointed out was wrong. That is, I assumed that you had actually tried
>using the "base." notation and that had failed. Obviously you hadn't,
>because it does work and as near as I can tell does just what you want
>it to.
>
No, "base." does not what I want, because the immediate base class has
no such method.
See Ben's reply. As Jeroen already pointed out, and now Ben and I both
have as well, "base." will provide access to the nearest base
implementation. It doesn't have to be in the immediately-inherited class.

Pete
Robert Fuchs
Guest
 
Posts: n/a
#12: Jun 27 '08

re: Accessing members which have been hidden by "new"


You cannot access a protected method that is hidden in your base class,
Quote:
only if your own class is the one hiding it.
it is in fact my own class which is hiding it, but it does not work, when it
is protected.
Quote:
Then it matters not how deep in the hierarchy the definition was provided.
that's not true - it matters.

regards, Robert

Jon Skeet [C# MVP]
Guest
 
Posts: n/a
#13: Jun 27 '08

re: Accessing members which have been hidden by "new"


Robert Fuchs <nix@nix.atwrote:
Quote:
Quote:
You cannot access a protected method that is hidden in your base class,
only if your own class is the one hiding it.
>
it is in fact my own class which is hiding it, but it does not work, when it
is protected.
>
Quote:
Then it matters not how deep in the hierarchy the definition was provided.
>
that's not true - it matters.
You have ignored Ben's request for code. Here's an example which
matches your original code but with BaseC.Invoke protected and with a
call to base.Invoke() from DerivedDerivedC.

using System;

public class BaseC
{
public int x;
protected void Invoke()
{
Console.WriteLine("BaseC.Invoke");
}
}

public class DerivedC : BaseC
{
public int y;
}

public class DerivedDerivedC : DerivedC
{
public int z;
new public void Invoke()
{
Console.WriteLine("DerivedDeriveC.Invoke");
base.Invoke();
}
}

class Test
{
static void Main()
{
new DerivedDerivedC().Invoke();
}
}

This compiles and runs without problem. Now, to repeat Ben's request,
could you post the code using "base." notation which *doesn't* work?

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
Closed Thread


Similar C# / C Sharp bytes