C# inheritance broken?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Bruce Wood

    #16
    Re: C# inheritance broken?



    On Jan 26, 9:06 am, gro...@isaacsof t.com wrote:
    C# is an impressive language...but it seems to have one big limitation
    that, from a C++ background, seems unacceptable.
    >
    Here's the problem:
    >
    I have a third-party Document class. (This means I can't change the
    Document class.) I want to extend this (inherit from Document) as
    MyDocument, adding new events and application-specific methods and
    properties.
    >
    I submit that this can't be done in C#.
    >
    <snip>
    >
    In C++, I would do something like this:
    >
    class MyDocument : public Document
    {
    public static MyDocument Load(string FileName)
    {
    return (MyDocument)Doc ument.Load(File Name);
    }
    Now, I'll state first off that I'm not a C++ guru. I used it briefly.

    That said, I'm having trouble imagining how this would work in any
    language. Let me modify your example a bit:

    class MyDocument : public Document
    {
    private int additionalFIeld = 15;

    public static MyDocument Load(string FileName)
    {
    return (MyDocument)Doc ument.Load(File Name);
    }
    }

    So... you're telling me that C++ somehow, magically, knows that when
    MyDocument.Load calls Document.Load it must allocate additional space
    for the object for the fields that are a part of MyDocument but not
    part of Document? How could it possibly know?

    OR

    Are you saying that in C++ you can cheat and cast a base type to a
    derived type and get away with it so long as the derived type has no
    additional fields? (And so, by inference, if the derived type _does_
    have additional fields then the cast still works but all hell breaks
    loose at runtime?)

    If you're suggesting the latter, then from a .NET point of view it is
    C++ that is "broken". .NET was explicitly designed to _not_ allow
    programmers to play fast and loose with objects. The whole idea is to
    _guarantee_ that casts are valid, and that pointers point to the right
    thing, so as to mitigate all sorts of hacking attacks that depend upon
    overlaying memory that contains one thing with a definition for a
    different thing and then having a field day with arbitrary operations
    in memory.

    For example, the following is perfectly legal C:

    char x[4];
    int *p = (int *)&x;
    int y = *p;

    Memory is plastic in C/C++: you can flip between types and the compiler
    assumes that you know what you're doing. In C#, the compiler assumes
    nothing. The compiler / CLR combine to make solid guarantees about what
    is what and what operations you're allowed to perform. As such, if you
    want to stick to what's called "safe" code in C#, you can't play these
    sorts of tricks. The compiler / runtime won't let you. There's nothing
    broken about it: just different design goals.

    Comment

    • Andy

      #17
      Re: C# inheritance broken?


      On Jan 26, 3:07 pm, gro...@isaacsof t.com wrote:
      Andy,
      >
      In your example, where does
      >
      DocumentLoader. Load( result, FileName );
      >
      come from?
      You build it of course ;-)
      ...and about the Toyota car, if they design one that requires you to
      crawl underneath to start it, that design is broken. :-)
      No, again, you disagree with the design, but its not broken, as long as
      you can in fact start the car.

      Comment

      • groups@isaacsoft.com

        #18
        Re: C# inheritance broken?

        Here is some more relevant information that I've just learned:

        The Document.Load static method relies on System.Runtime. Serialization
        to create a new Document object. Formatter.Deser ialize returns an
        object that is a Document, and this Document object can't be cast to a
        MyDocument. Deserialization can't occur in a constructor, because the
        Document object already exists, and you can't replace "this" with the
        new Document object.

        So it would seem that the limitation is there because of the way
        serialization works, not because of a bad design on the part of the
        author of Document.

        Tony

        On Jan 26, 2:07 pm, gro...@isaacsof t.com wrote:
        Andy,
        >
        In your example, where does
        >
        DocumentLoader. Load( result, FileName );
        >
        come from?
        >
        ...and about the Toyota car, if they design one that requires you to
        crawl underneath to start it, that design is broken. :-)
        >
        Tony
        >
        On Jan 26, 1:45 pm, "Andy" <a...@med-associates.comw rote:
        >
        >
        >
        On Jan 26, 1:21 pm, gro...@isaacsof t.com wrote:
        >
        Thanks for your response. My assertion is that the DESIGN is broken!
        But I'll settle for a work-around, if there is one.The design can't be broken, by definition. The design dictates how a
        piece of software should function, and C# functions as designed. Now,
        you may disagree with the design decision, and that's another topic,
        but to say its broken is wrong. Is a Toyota car's design broken
        because it doesn't have as much horsepower as my car? No.
        >
        If I understand your suggestion, I've already tried this. But...I
        don't have any problem creating a new MyDocument object when I need it;
        my problem is loading a MyDocument from a file. There is only one
        method in Document that does this:
        >
        class Document
        {
        public static Document Load(string FileName);
        >
        }I can certainly write a new Load method to override the base method, as
        follows:
        >
        class MyDocument : Document
        {
        public static MyDocument Load(string FileName)
        {
        return Document.Load(F ileName);
        }
        >
        }The problem is, the above code won't compile, because it is not valid
        to cast the Document returned by Document.Load to a MyDocument.
        >
        Does that make sense?Not at all. You should be coding to abstracts. If you really need
        MyDocument, then you'll instantiate MyDocument and not the base class.
        >
        If you want that code to work, its pretty simple:
        >
        public static MyDocument Load(string FileName)
        {
        MyDocument result;
        >
        result = new MyDocument();
        DocumentLoader. Load( result, FileName );
        >
        return result;
        >
        }The loading of your document is now abstracted away from the document
        itself, which is a good thing.- Hide quoted text -- Show quoted text -- Hide quoted text -- Show quoted text -

        Comment

        • Mark Wilden

          #19
          Re: C# inheritance broken?

          <groups@isaacso ft.comwrote in message
          news:1169841570 .248959.318230@ k78g2000cwa.goo glegroups.com.. .
          As I pointed out before, C++
          does indeed allow you to write such a "helper" class; you can use
          reinterpret_cas t to transform Document into a MyDocument.
          Is this quite true? My understanding is that <reinterpret_ca stsimply
          performs an explicitly unsafe case of a pointer. It doesn't transform
          anything. In this case, if a Document is created, it can never be
          "transforme d" into another type.

          ///ark


          Comment

          • groups@isaacsoft.com

            #20
            Re: C# inheritance broken?

            >You build it of course ;-)

            Hmmm...I'm not sure how that would happen. I'm still stuck with the
            fact that the third-party component's Load method returns a Document,
            which can't be converted to type MyDocument, even in DocumentLoader.

            Tony

            On Jan 26, 2:23 pm, "Andy" <a...@med-associates.comw rote:
            On Jan 26, 3:07 pm, gro...@isaacsof t.com wrote:
            >
            Andy,
            >
            In your example, where does
            >
            DocumentLoader. Load( result, FileName );
            >
            come from?You build it of course ;-)
            >
            ...and about the Toyota car, if they design one that requires you to
            crawl underneath to start it, that design is broken. :-)No, again, you disagree with the design, but its not broken, as long as
            you can in fact start the car.

            Comment

            • groups@isaacsoft.com

              #21
              Re: C# inheritance broken?

              Mark,

              Yes, reinterpret_cas t is indeed unsafe. But if there are no added
              members, it works, as in CRect : RECT.

              But this strays from what I'm hoping to accomplish.

              How is it that serialization can magically create a Document object
              through casting an "object" to "Document," but I'm not allowed to use
              the same trick to create a MyDocument instead? The Serialization
              classes don't know about Document while deserialization is occuring,
              but it still lets you cast the return value of Deserialize into a
              Document type. What is the trick they are using?

              Tony

              On Jan 26, 2:30 pm, "Mark Wilden" <mwil...@commun itymtm.comwrote :
              <gro...@isaacso ft.comwrote in messagenews:116 9841570.248959. 318230@k78g2000 cwa.googlegroup s.com...
              >
              As I pointed out before, C++
              does indeed allow you to write such a "helper" class; you can use
              reinterpret_cas t to transform Document into a MyDocument.Is this quite true? My understanding is that <reinterpret_ca stsimply
              performs an explicitly unsafe case of a pointer. It doesn't transform
              anything. In this case, if a Document is created, it can never be
              "transforme d" into another type.
              >
              ///ark

              Comment

              • Bruce Wood

                #22
                Re: C# inheritance broken?



                On Jan 26, 12:53 pm, gro...@isaacsof t.com wrote:
                Mark,
                >
                Yes, reinterpret_cas t is indeed unsafe. But if there are no added
                members, it works, as in CRect : RECT.
                >
                But this strays from what I'm hoping to accomplish.
                >
                How is it that serialization can magically create a Document object
                through casting an "object" to "Document," but I'm not allowed to use
                the same trick to create a MyDocument instead?
                Because .NET doesn't trust you. :-)

                One of the goals of .NET was to produce code that was immune to the
                sort of run-time memory hacking that is rampant in C and C++. If the
                runtime lets you play tricks like reinterpret_cas t, then the code can't
                be verifiably safe, can it?

                As I said in my other post: different design goals. One goal of C++ was
                to give the programmer total power to do whatever he wants, and the
                compiler will trust him to get it right (by generating code no matter
                what it might do at runtime). One goal of C# is to produce only code
                that can be verified to not clobber memory / reinterpret memory
                patterns as that which they are not / etc.

                The two design goals are, obviously, incompatible.

                If you want to do this sort of thing in C#, you have to use the
                "unsafe" keyword to tell the compiler / runtime to lay off, but even
                then I'm not sure of just how far you can go with that, because I've
                never used it.

                Comment

                • Ignacio Machin \( .NET/ C# MVP \)

                  #23
                  Re: C# inheritance broken?

                  Hi,

                  <groups@isaacso ft.comwrote in message
                  news:1169843950 .469459.130550@ s48g2000cws.goo glegroups.com.. .
                  | >You build it of course ;-)
                  |
                  | Hmmm...I'm not sure how that would happen. I'm still stuck with the
                  | fact that the third-party component's Load method returns a Document,
                  | which can't be converted to type MyDocument, even in DocumentLoader.

                  You simply have a crappy component :)


                  Use other


                  --
                  Ignacio Machin
                  machin AT laceupsolutions com


                  Comment

                  • Ignacio Machin \( .NET/ C# MVP \)

                    #24
                    Re: C# inheritance broken?

                    Hi,

                    "Michael D. Ober" <obermd.@.alum. mit.edu.nospamw rote in message
                    news:45ba5844$0 $700$815e3792@n ews.qwest.net.. .

                    | --
                    | Ignacio Machin
                    | machin AT laceupsolutions com
                    | >
                    | This isn't a C# issue. It is a dotNet issue as I have run into the same
                    | issue of inheriting a base class (in my case, VB 2005 and
                    StringCollectio n)
                    | and providing a method for the base class object to become the object at
                    the
                    | heart of the derived class.

                    Not at all, A base class cannot become a derived class, A derived class can
                    be treated as a base class without any problem.

                    Think about, what would hppen if the derived object add a new property,
                    clearly the base does not has it , so what can the compiler do in this
                    case??

                    | This is a design limitation in the framework

                    No, it's simply bad design of the base class, or trying to made a bad use of
                    the class.



                    Comment

                    • Bruce Wood

                      #25
                      Re: C# inheritance broken?



                      On Jan 26, 11:36 am, "Michael D. Ober" <obermd.@.alum. mit.edu.nospam>
                      wrote:
                      "Ignacio Machin ( .NET/ C# MVP )" <machin TA laceupsolutions .comwrote in
                      messagenews:%23 1AcH4XQHHA.496@ TK2MSFTNGP06.ph x.gbl...
                      >
                      >
                      >
                      Hi,
                      >
                      "Mythran" <kip_pot...@hot mail.comwrote in message
                      news:e8FyEvXQHH A.4896@TK2MSFTN GP04.phx.gbl...
                      |
                      |
                      | <gro...@isaacso ft.comwrote in message
                      |news:116983707 6.386389.190580 @v45g2000cwv.go oglegroups.com. ..
                      | Ignacio,
                      | >
                      | Thank you for your thoughts.
                      | >
                      | The Document class does have a public default constructor, and it is
                      | not sealed. I have no problem creating a "new" Document object, or a
                      | "new" MyDocument object, for that matter. What I can't do is
                      "convert"
                      | an existing Document object (such as the one returned by
                      Document.Load)
                      | into a MyDocument.
                      >
                      As I said in another post, giving the struct you are presenting you would
                      have the same issue no matter what language you use. You cannot treat a
                      base
                      class as a derived class, you can do the opposite though.
                      >
                      In your case you will have to implement your own Load method. I would
                      first
                      check though if Document provide a Load method instance. or maybe a Clone
                      method
                      >
                      --
                      Ignacio Machin
                      machin AT laceupsolutions comThis isn't a C# issue. It is a dotNet issue as I have run into the same
                      issue of inheriting a base class (in my case, VB 2005 and StringCollectio n)
                      and providing a method for the base class object to become the object at the
                      heart of the derived class. This is a design limitation in the framework
                      itself. From a business logic perspective, it should be doable.
                      For the record, no language that I know of lets you do this. C++ allows
                      you to pretend to do it via an unsafe cast, but you're not really
                      getting a derived object, just playing with a base class object as
                      though it were a derived object, which is fodder for disaster unless
                      you keep careful track of what you're doing.

                      You can't use a base class instance as though it were a derived class
                      instance because the latter may have more fields than the former, and
                      so the base class instance doesn't have enough space to store the state
                      of the derived class.

                      There _are_ various strategies for using a base class instance as a
                      model for creating a derived class. Most of them, however, require some
                      coding. There's no "automatic" way of copying state from one instance
                      to another, which might be a nice addition.

                      Comment

                      • rossum

                        #26
                        Re: C# inheritance broken?

                        On 26 Jan 2007 12:26:15 -0800, groups@isaacsof t.com wrote:
                        >Here is some more relevant information that I've just learned:
                        >
                        >The Document.Load static method relies on System.Runtime. Serialization
                        >to create a new Document object. Formatter.Deser ialize returns an
                        >object that is a Document, and this Document object can't be cast to a
                        >MyDocument. Deserialization can't occur in a constructor, because the
                        >Document object already exists, and you can't replace "this" with the
                        >new Document object.
                        >
                        >So it would seem that the limitation is there because of the way
                        >serializatio n works, not because of a bad design on the part of the
                        >author of Document.
                        >
                        >Tony
                        Taking a completely different tack, how easy would it be for you to
                        parse through the Serialized Document file and change it to whatever
                        the equivalent Serialized MyDocument file would look like?

                        Given that you are trying to upcast the derived class, which goes
                        against the design goals of C#, this might be an easier way to work
                        round your problem.

                        rossum

                        Comment

                        • groups@isaacsoft.com

                          #27
                          Re: C# inheritance broken?

                          No, it's simply bad design of the base class, or trying to made a bad use of
                          the class.
                          OK, please enlighten me. What would be the proper design of the base
                          class? I see no way to inherit from such a base class, regardless of
                          the base class design!

                          Tony

                          On Jan 26, 4:44 pm, "Ignacio Machin \( .NET/ C# MVP \)" <machin TA
                          laceupsolutions .comwrote:
                          Hi,
                          >
                          "Michael D. Ober" <obermd.@.alum. mit.edu.nospamw rote in messagenews:45b a5844$0$700$815 e3792@news.qwes t.net...
                          >
                          | --
                          | Ignacio Machin
                          | machin AT laceupsolutions com
                          | >
                          | This isn't a C# issue. It is a dotNet issue as I have run into the same
                          | issue of inheriting a base class (in my case, VB 2005 and
                          StringCollectio n)
                          | and providing a method for the base class object to become the object at
                          the
                          | heart of the derived class.
                          >
                          Not at all, A base class cannot become a derived class, A derived class can
                          be treated as a base class without any problem.
                          >
                          Think about, what would hppen if the derived object add a new property,
                          clearly the base does not has it , so what can the compiler do in this
                          case??
                          >
                          | This is a design limitation in the framework
                          >
                          No, it's simply bad design of the base class, or trying to made a bad use of
                          the class.

                          Comment

                          • Michael D. Ober

                            #28
                            Re: C# inheritance broken?


                            "Bruce Wood" <brucewood@cana da.comwrote in message
                            news:1169856962 .726497.102330@ a75g2000cwd.goo glegroups.com.. .
                            >
                            >
                            On Jan 26, 11:36 am, "Michael D. Ober" <obermd.@.alum. mit.edu.nospam>
                            wrote:
                            >"Ignacio Machin ( .NET/ C# MVP )" <machin TA laceupsolutions .comwrote
                            >in
                            >messagenews:%2 31AcH4XQHHA.496 @TK2MSFTNGP06.p hx.gbl...
                            >>
                            >>
                            >>
                            Hi,
                            >>
                            "Mythran" <kip_pot...@hot mail.comwrote in message
                            >news:e8FyEvXQH HA.4896@TK2MSFT NGP04.phx.gbl.. .
                            |
                            |
                            | <gro...@isaacso ft.comwrote in message
                            |news:116983707 6.386389.190580 @v45g2000cwv.go oglegroups.com. ..
                            | Ignacio,
                            | >
                            | Thank you for your thoughts.
                            | >
                            | The Document class does have a public default constructor, and it
                            is
                            | not sealed. I have no problem creating a "new" Document object, or
                            a
                            | "new" MyDocument object, for that matter. What I can't do is
                            "convert"
                            | an existing Document object (such as the one returned by
                            Document.Load)
                            | into a MyDocument.
                            >>
                            As I said in another post, giving the struct you are presenting you
                            would
                            have the same issue no matter what language you use. You cannot treat a
                            base
                            class as a derived class, you can do the opposite though.
                            >>
                            In your case you will have to implement your own Load method. I would
                            first
                            check though if Document provide a Load method instance. or maybe a
                            Clone
                            method
                            >>
                            --
                            Ignacio Machin
                            machin AT laceupsolutions comThis isn't a C# issue. It is a dotNet
                            issue as I have run into the same
                            >issue of inheriting a base class (in my case, VB 2005 and
                            >StringCollecti on)
                            >and providing a method for the base class object to become the object at
                            >the
                            >heart of the derived class. This is a design limitation in the framework
                            >itself. From a business logic perspective, it should be doable.
                            >
                            For the record, no language that I know of lets you do this. C++ allows
                            you to pretend to do it via an unsafe cast, but you're not really
                            getting a derived object, just playing with a base class object as
                            though it were a derived object, which is fodder for disaster unless
                            you keep careful track of what you're doing.
                            >
                            You can't use a base class instance as though it were a derived class
                            instance because the latter may have more fields than the former, and
                            so the base class instance doesn't have enough space to store the state
                            of the derived class.
                            >
                            There _are_ various strategies for using a base class instance as a
                            model for creating a derived class. Most of them, however, require some
                            coding. There's no "automatic" way of copying state from one instance
                            to another, which might be a nice addition.
                            >
                            A generalized method of converting a base class into a derived class with
                            the knowledge that the derived class may still require some initialization
                            would definitely be useful, even if you had to do it via a constructor that
                            takes an object of the base class as it's argument. The missing syntax, in
                            vb is

                            mybase = objBaseClass

                            In C# I think it would be

                            base = objBaseClass

                            In either case, since this is occurring in a constructor in place of the
                            base.New() or mybase.New statement, the programmer knows he still has to
                            instantiate and initialize all other private and protected objects in the
                            derived class.

                            Mike Ober.



                            Comment

                            • Jon Skeet [C# MVP]

                              #29
                              Re: C# inheritance broken?

                              <groups@isaacso ft.comwrote:
                              No, it's simply bad design of the base class, or trying to made a bad use of
                              the class.
                              >
                              OK, please enlighten me. What would be the proper design of the base
                              class? I see no way to inherit from such a base class, regardless of
                              the base class design!
                              Instead of having a static method which returns a Document, create an
                              *instance* method which loads data into an existing instance. That's
                              the way XmlDocumentLoad works, for example.

                              --
                              Jon Skeet - <skeet@pobox.co m>
                              http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
                              If replying to the group, please do not mail me too

                              Comment

                              • Jake Stevenson

                                #30
                                Re: C# inheritance broken?

                                What is wrong with this approach?

                                class MyDocument : Document
                                {
                                public void CopyFromDocumen t(Document Original)
                                {
                                foreach (System.Reflect ion.PropertyInf o Prop in
                                Original.GetTyp e().GetProperti es())
                                {
                                if (Prop.CanWrite)
                                {
                                Prop.SetValue(t his, Prop.GetValue(O riginal, null),
                                null);
                                }
                                }
                                foreach (System.Reflect ion.FieldInfo Field in
                                Original.GetTyp e().GetFields() )
                                {
                                Field.SetValue( this, Field.GetValue( Original));
                                }
                                }
                                }

                                Something similar can be implemented in the base class and would be
                                inherited by your class. There may be a performance issue with
                                Reflection though.


                                Comment

                                Working...