Accessing members which have been hidden by "new"

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Robert Fuchs

    #1

    Accessing members which have been hidden by "new"

    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

    #2
    Re: Accessing members which have been hidden by "new&qu ot;

    On Mon, 21 Apr 2008 15:34:04 -0700, Robert Fuchs <nix@nix.atwrot e:
    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.
    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

    Comment

    • Robert Fuchs

      #3
      Re: Accessing members which have been hidden by &quot;new&qu ot;

      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)thi s).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

      Comment

      • Jeroen Mostert

        #4
        Re: Accessing members which have been hidden by &quot;new&qu ot;

        Peter Duniho wrote:
        On Mon, 21 Apr 2008 15:34:04 -0700, Robert Fuchs <nix@nix.atwrot e:
        >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.

        Comment

        • John B

          #5
          Re: Accessing members which have been hidden by &quot;new&qu ot;

          Peter Duniho wrote:
          <...>
          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{g et;}
          }

          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

          Comment

          • Peter Duniho

            #6
            Re: Accessing members which have been hidden by &quot;new&qu ot;

            On Mon, 21 Apr 2008 16:39:59 -0700, Robert Fuchs <nix@nix.atwrot e:
            >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)thi s).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.WriteLi ne("A.MethodA") ; }
            protected void MethodC() { Console.WriteLi ne("A.MethodC") ; }
            }

            class B : A
            {
            }

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

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

            base.MethodA(); // this works
            c.MethodC(); // this works
            // ((A)this).Metho dA(); // this doesn't
            // ((A)c).MethodA( ); // this doesn't
            }
            }
            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

            Comment

            • Peter Duniho

              #7
              Re: Accessing members which have been hidden by &quot;new&qu ot;

              On Mon, 21 Apr 2008 18:10:22 -0700, John B <jbngspam@yahoo .comwrote:
              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{g et;}
              }
              >
              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

              Comment

              • John B

                #8
                Re: Accessing members which have been hidden by &quot;new&qu ot;

                Peter Duniho wrote:
                On Mon, 21 Apr 2008 18:10:22 -0700, John B <jbngspam@yahoo .comwrote:
                >
                >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{g et;}
                >}
                >>
                >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.
                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).
                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.TypedV alue so I'd have to remember to always use
                TypedValue.
                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 CustomerSurname Criteria : Criteria<Custom erFields, string>
                {
                public override CustomerFields Field
                {
                get { return CustomerFields. Surname; }
                }
                }

                Comment

                • Robert Fuchs

                  #9
                  Re: Accessing members which have been hidden by &quot;new&qu ot;

                  >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.
                  That is exactly the point why I asked.
                  I would need something like "base.base. " ;-)

                  regards, Robert

                  Comment

                  • Ben Voigt [C++ MVP]

                    #10
                    Re: Accessing members which have been hidden by &quot;new&qu ot;

                    Robert Fuchs wrote:
                    >>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.
                    That is exactly the point why I asked.
                    I would need something like "base.base. " ;-)
                    >
                    regards, Robert

                    Comment

                    • Peter Duniho

                      #11
                      Re: Accessing members which have been hidden by &quot;new&qu ot;

                      On Wed, 23 Apr 2008 04:54:49 -0700, Robert Fuchs <nix@nix.atwrot e:
                      >>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

                      Comment

                      • Robert Fuchs

                        #12
                        Re: Accessing members which have been hidden by &quot;new&qu ot;

                        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.
                        Then it matters not how deep in the hierarchy the definition was provided.
                        that's not true - it matters.

                        regards, Robert

                        Comment

                        • Jon Skeet [C# MVP]

                          #13
                          Re: Accessing members which have been hidden by &quot;new&qu ot;

                          Robert Fuchs <nix@nix.atwrot e:
                          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.
                          >
                          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.WriteLi ne("BaseC.Invok e");
                          }
                          }

                          public class DerivedC : BaseC
                          {
                          public int y;
                          }

                          public class DerivedDerivedC : DerivedC
                          {
                          public int z;
                          new public void Invoke()
                          {
                          Console.WriteLi ne("DerivedDeri veC.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.co m>
                          http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
                          World class .NET training in the UK: http://iterativetraining.co.uk

                          Comment

                          Working...