Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Web Development
  3. ASP.NET
  4. How do I change this code using Inheritance?

How do I change this code using Inheritance?

Scheduled Pinned Locked Moved ASP.NET
questioncsharplinqxmljson
14 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Marc Hede

    Yeah, that is also how I thought I should do it. But I am getting a ton of errors when doing so. "Person does not contain a constructor that takes 0 arguements" "mykey does not exist within current context" "method must have a return type" This is how I wrote it

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Formatters.Binary;

    namespace Keycard
    {
    [Serializable()]
    public class Person : ISerializable
    {
    protected string name;

        public Person(string name)
        {
            this.Name = name;
        }
    
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    
        \[Serializable()\]
        public class Keycard : Person
        {
            protected int mykey;
    
            public Keycard(int mykey)
            {
                this.Mykey = mykey;
            }
            public int Mykey
            {
                get { return mykey; }
                set { mykey = value; }
            }
        }
    
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
    
            info.AddValue("Name", name);
            info.AddValue("Keynumber", mykey);
    
        }
        public Person(SerializationInfo info, StreamingContext context)
        {
            Name = (string)info.GetValue("Name", typeof(string));
        }
        public Keycard(SerializationInfo info, StreamingContext context)
        {
            Mykey = (int)info.GetValue("Keynumber", typeof(int));
        }
    
        public override string ToString()
        {
            return "Name: " + name + " ---- " + " Keynumber: " + mykey;
        }
    }
    

    }

    P Offline
    P Offline
    phil o
    wrote on last edited by
    #5

    Marc Hede wrote:

    "Person does not contain a constructor that takes 0 arguements"

    The Person class has a single constructor accepting a string value as argument. Defining a constructor also means that the class does not have any default parameterless constructor. Since the KeyCard class inherits from Person, it has to provide its base class a name argument (so that the base class can be constructed). There are several solutions to this:

    1. you can define a parameterless constructor in the base class.
    2. you can delete defined constructor in base class (so that compiler generate a default, parameterless one); but this "solution" is not really clever.
    3. you can provide a default name argument in KeyCard's constructor.

    In clear:

    #region Solution 1 : Defining a parameterless constructor

    public class Person
    {
    // ...
    public Person() : this("unnamed") { }
    }

    #endregion

    #region Solution 3 : providing a default name in inherited classs' constructor

    public class KeyCard : Person
    {
    // ...
    public KeyCard(int mykey) : base("unnamed")
    {
    // ...
    }

    // and/or

    public KeyCard(string name) : base(name)
    {
    this.Mykey = -1;
    }

    public KeyCard(string name, int mykey) : base(name)
    {
    this.Mykey = mykey;
    }
    }

    #endregion

    Marc Hede wrote:

    "mykey does not exist within current context"

    The compiler does not how to differentiate the mykey parameter of the constructor from the protected mykey field. You can either rename one of them, or just define an auto-implemented property and get rid of the protected field:

    public int Mykey { get; set; }

    Marc Hede wrote:

    "method must have a return type"

    Probably because you defined the KeyCard class inside the Person class, and then defined a KeyCard constructor inside Person (which is incorrect). Please get the KeyCard class out of the Person (you do not need to nest inheriting classes), and put constructors and methods in the class to which they properly belong. Good work :)

    "Five fruits and vegetables a day? What a joke! Personally, after the thir

    M 1 Reply Last reply
    0
    • P phil o

      Marc Hede wrote:

      "Person does not contain a constructor that takes 0 arguements"

      The Person class has a single constructor accepting a string value as argument. Defining a constructor also means that the class does not have any default parameterless constructor. Since the KeyCard class inherits from Person, it has to provide its base class a name argument (so that the base class can be constructed). There are several solutions to this:

      1. you can define a parameterless constructor in the base class.
      2. you can delete defined constructor in base class (so that compiler generate a default, parameterless one); but this "solution" is not really clever.
      3. you can provide a default name argument in KeyCard's constructor.

      In clear:

      #region Solution 1 : Defining a parameterless constructor

      public class Person
      {
      // ...
      public Person() : this("unnamed") { }
      }

      #endregion

      #region Solution 3 : providing a default name in inherited classs' constructor

      public class KeyCard : Person
      {
      // ...
      public KeyCard(int mykey) : base("unnamed")
      {
      // ...
      }

      // and/or

      public KeyCard(string name) : base(name)
      {
      this.Mykey = -1;
      }

      public KeyCard(string name, int mykey) : base(name)
      {
      this.Mykey = mykey;
      }
      }

      #endregion

      Marc Hede wrote:

      "mykey does not exist within current context"

      The compiler does not how to differentiate the mykey parameter of the constructor from the protected mykey field. You can either rename one of them, or just define an auto-implemented property and get rid of the protected field:

      public int Mykey { get; set; }

      Marc Hede wrote:

      "method must have a return type"

      Probably because you defined the KeyCard class inside the Person class, and then defined a KeyCard constructor inside Person (which is incorrect). Please get the KeyCard class out of the Person (you do not need to nest inheriting classes), and put constructors and methods in the class to which they properly belong. Good work :)

      "Five fruits and vegetables a day? What a joke! Personally, after the thir

      M Offline
      M Offline
      Marc Hede
      wrote on last edited by
      #6

      Hey Phil. Thanks a lot I almost got it to work. Only one error left thankfully.

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Web;
      using System.Runtime.Serialization;
      using System.Runtime.Serialization.Formatters.Binary;

      namespace Keycard
      {
      [Serializable()]
      public class Person : ISerializable
      {
      protected string name;

          public Person(string name)
          {
              this.Name = name;
          }
      
          public string Name
          {
              get { return name; }
              set { name = value; }
          }
      
          public void GetObjectData(SerializationInfo info, StreamingContext context)
          {
      
              info.AddValue("Name", name);
      
          }
          public Person(SerializationInfo info, StreamingContext context)
          {
              Name = (string)info.GetValue("Name", typeof(string));
          }
      }
      \[Serializable()\]
      public class Keycard : Person
      {
          protected int mykey;
      
          public Keycard(string name)
              : base (name)
          {
              this.Mykey = -1;
          }
          public Keycard(string name, int mykey) : base(name)
          {
              this.Mykey = mykey;
          }
          public int Mykey
          {
              get { return mykey;  }
              set { mykey = value; }
          }
      
          public new void GetObjectData(SerializationInfo info, StreamingContext context)
          {
      
              info.AddValue("Keynumber", mykey);
      
          }
          public Keycard(SerializationInfo info, StreamingContext context)
          {
             Mykey = (int)info.GetValue("Keynumber", typeof(int));
          }
          public override string ToString()
          {
              return "Name: " + name + " ---- " + " Keynumber: " + mykey;
          }
      }
      

      }

      The only problem here is this line

      public Keycard(SerializationInfo info, StreamingContext context)

      I get the constructor error again. I understood your solution with the default name arguement, but how do I apply that logic here?

      F L 2 Replies Last reply
      0
      • M Marc Hede

        Hey Phil. Thanks a lot I almost got it to work. Only one error left thankfully.

        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Web;
        using System.Runtime.Serialization;
        using System.Runtime.Serialization.Formatters.Binary;

        namespace Keycard
        {
        [Serializable()]
        public class Person : ISerializable
        {
        protected string name;

            public Person(string name)
            {
                this.Name = name;
            }
        
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
        
            public void GetObjectData(SerializationInfo info, StreamingContext context)
            {
        
                info.AddValue("Name", name);
        
            }
            public Person(SerializationInfo info, StreamingContext context)
            {
                Name = (string)info.GetValue("Name", typeof(string));
            }
        }
        \[Serializable()\]
        public class Keycard : Person
        {
            protected int mykey;
        
            public Keycard(string name)
                : base (name)
            {
                this.Mykey = -1;
            }
            public Keycard(string name, int mykey) : base(name)
            {
                this.Mykey = mykey;
            }
            public int Mykey
            {
                get { return mykey;  }
                set { mykey = value; }
            }
        
            public new void GetObjectData(SerializationInfo info, StreamingContext context)
            {
        
                info.AddValue("Keynumber", mykey);
        
            }
            public Keycard(SerializationInfo info, StreamingContext context)
            {
               Mykey = (int)info.GetValue("Keynumber", typeof(int));
            }
            public override string ToString()
            {
                return "Name: " + name + " ---- " + " Keynumber: " + mykey;
            }
        }
        

        }

        The only problem here is this line

        public Keycard(SerializationInfo info, StreamingContext context)

        I get the constructor error again. I understood your solution with the default name arguement, but how do I apply that logic here?

        F Offline
        F Offline
        F ES Sitecore
        wrote on last edited by
        #7

        public Keycard(SerializationInfo info, StreamingContext context)
        : base ("unnamed")
        {
        Mykey = (int)info.GetValue("Keynumber", typeof(int));
        }

        M 1 Reply Last reply
        0
        • M Marc Hede

          Hey Phil. Thanks a lot I almost got it to work. Only one error left thankfully.

          using System;
          using System.Collections.Generic;
          using System.Linq;
          using System.Web;
          using System.Runtime.Serialization;
          using System.Runtime.Serialization.Formatters.Binary;

          namespace Keycard
          {
          [Serializable()]
          public class Person : ISerializable
          {
          protected string name;

              public Person(string name)
              {
                  this.Name = name;
              }
          
              public string Name
              {
                  get { return name; }
                  set { name = value; }
              }
          
              public void GetObjectData(SerializationInfo info, StreamingContext context)
              {
          
                  info.AddValue("Name", name);
          
              }
              public Person(SerializationInfo info, StreamingContext context)
              {
                  Name = (string)info.GetValue("Name", typeof(string));
              }
          }
          \[Serializable()\]
          public class Keycard : Person
          {
              protected int mykey;
          
              public Keycard(string name)
                  : base (name)
              {
                  this.Mykey = -1;
              }
              public Keycard(string name, int mykey) : base(name)
              {
                  this.Mykey = mykey;
              }
              public int Mykey
              {
                  get { return mykey;  }
                  set { mykey = value; }
              }
          
              public new void GetObjectData(SerializationInfo info, StreamingContext context)
              {
          
                  info.AddValue("Keynumber", mykey);
          
              }
              public Keycard(SerializationInfo info, StreamingContext context)
              {
                 Mykey = (int)info.GetValue("Keynumber", typeof(int));
              }
              public override string ToString()
              {
                  return "Name: " + name + " ---- " + " Keynumber: " + mykey;
              }
          }
          

          }

          The only problem here is this line

          public Keycard(SerializationInfo info, StreamingContext context)

          I get the constructor error again. I understood your solution with the default name arguement, but how do I apply that logic here?

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #8

          Inheriting Keycard from Person really makes no sense. A Keycard is a piece of plastic at best, not a human being.

          M 1 Reply Last reply
          0
          • F F ES Sitecore

            public Keycard(SerializationInfo info, StreamingContext context)
            : base ("unnamed")
            {
            Mykey = (int)info.GetValue("Keynumber", typeof(int));
            }

            M Offline
            M Offline
            Marc Hede
            wrote on last edited by
            #9

            Ah of course. Sometimes it surprises me how simple the solution is. I tend to overthink things :-D The only issue now is that I get a

            System.Runtime.Serialization.SerializationException

            at

            Mykey = (int)info.GetValue("Keynumber", typeof(int));

            Do I need to add Keynumber in my other class file?

            using System;
            using System.Collections;
            using System.Collections.Generic;
            using System.Linq;
            using System.Xml.Serialization;
            using System.IO;
            using System.Runtime.Serialization.Formatters.Binary;

            namespace Keycard
            {
            class Class1
            {
            public static void Main(string[] args)
            {
            Keycard k1 = new Keycard("John", 123);

                    Stream stream = File.Open("KeycardData.dat",
                        FileMode.Create);
            
                    BinaryFormatter bf = new BinaryFormatter();
            
                    bf.Serialize(stream, k1);
                    stream.Close();
            
                    k1 = null;
            
                    stream = File.Open("KeycardData.dat", FileMode.Open);
            
                    bf = new BinaryFormatter();
            
                    k1 = (Keycard)bf.Deserialize(stream);
                    stream.Close();
                    Console.WriteLine(k1.ToString());
                    Console.ReadLine();
                }
            
            }
            

            }

            P F Richard DeemingR 3 Replies Last reply
            0
            • L Lost User

              Inheriting Keycard from Person really makes no sense. A Keycard is a piece of plastic at best, not a human being.

              M Offline
              M Offline
              Marc Hede
              wrote on last edited by
              #10

              I know, but it is a requirement for a project I am making at my university. My teacher has told me to find help to solve these problems online, and that is why I am here. It was also his requirement to put binary code on a web page, and I still think it sounds illogical. But upon reading your comments, I am happy that I am not the only one who thinks this way. I have spent 2 weeks now trying to put binary code inside a web page, and I thought it was me who had overlooked something... Anyway, I just need help fixing the System.Runtime.Serialization.SerializationException error (the one I mention in the previous post), and then I hopefully won't have to ask for anymore help. I know as programmers it must be annoying having to create solutions that do not make sense :)

              L 1 Reply Last reply
              0
              • M Marc Hede

                I know, but it is a requirement for a project I am making at my university. My teacher has told me to find help to solve these problems online, and that is why I am here. It was also his requirement to put binary code on a web page, and I still think it sounds illogical. But upon reading your comments, I am happy that I am not the only one who thinks this way. I have spent 2 weeks now trying to put binary code inside a web page, and I thought it was me who had overlooked something... Anyway, I just need help fixing the System.Runtime.Serialization.SerializationException error (the one I mention in the previous post), and then I hopefully won't have to ask for anymore help. I know as programmers it must be annoying having to create solutions that do not make sense :)

                L Offline
                L Offline
                Lost User
                wrote on last edited by
                #11

                Marc Hede wrote:

                It was also his requirement to put binary code on a web page

                I think you need to ask him to explain what that means. As it stands it means nothing.

                1 Reply Last reply
                0
                • M Marc Hede

                  Ah of course. Sometimes it surprises me how simple the solution is. I tend to overthink things :-D The only issue now is that I get a

                  System.Runtime.Serialization.SerializationException

                  at

                  Mykey = (int)info.GetValue("Keynumber", typeof(int));

                  Do I need to add Keynumber in my other class file?

                  using System;
                  using System.Collections;
                  using System.Collections.Generic;
                  using System.Linq;
                  using System.Xml.Serialization;
                  using System.IO;
                  using System.Runtime.Serialization.Formatters.Binary;

                  namespace Keycard
                  {
                  class Class1
                  {
                  public static void Main(string[] args)
                  {
                  Keycard k1 = new Keycard("John", 123);

                          Stream stream = File.Open("KeycardData.dat",
                              FileMode.Create);
                  
                          BinaryFormatter bf = new BinaryFormatter();
                  
                          bf.Serialize(stream, k1);
                          stream.Close();
                  
                          k1 = null;
                  
                          stream = File.Open("KeycardData.dat", FileMode.Open);
                  
                          bf = new BinaryFormatter();
                  
                          k1 = (Keycard)bf.Deserialize(stream);
                          stream.Close();
                          Console.WriteLine(k1.ToString());
                          Console.ReadLine();
                      }
                  
                  }
                  

                  }

                  P Offline
                  P Offline
                  phil o
                  wrote on last edited by
                  #12

                  Technically, you do not need to provide any customized serialization code for an integer member variable; the Serializable attribute on its own will do just fine.

                  "Five fruits and vegetables a day? What a joke! Personally, after the third watermelon, I'm full."

                  1 Reply Last reply
                  0
                  • M Marc Hede

                    Ah of course. Sometimes it surprises me how simple the solution is. I tend to overthink things :-D The only issue now is that I get a

                    System.Runtime.Serialization.SerializationException

                    at

                    Mykey = (int)info.GetValue("Keynumber", typeof(int));

                    Do I need to add Keynumber in my other class file?

                    using System;
                    using System.Collections;
                    using System.Collections.Generic;
                    using System.Linq;
                    using System.Xml.Serialization;
                    using System.IO;
                    using System.Runtime.Serialization.Formatters.Binary;

                    namespace Keycard
                    {
                    class Class1
                    {
                    public static void Main(string[] args)
                    {
                    Keycard k1 = new Keycard("John", 123);

                            Stream stream = File.Open("KeycardData.dat",
                                FileMode.Create);
                    
                            BinaryFormatter bf = new BinaryFormatter();
                    
                            bf.Serialize(stream, k1);
                            stream.Close();
                    
                            k1 = null;
                    
                            stream = File.Open("KeycardData.dat", FileMode.Open);
                    
                            bf = new BinaryFormatter();
                    
                            k1 = (Keycard)bf.Deserialize(stream);
                            stream.Close();
                            Console.WriteLine(k1.ToString());
                            Console.ReadLine();
                        }
                    
                    }
                    

                    }

                    F Offline
                    F Offline
                    F ES Sitecore
                    wrote on last edited by
                    #13

                    Ok, I understands what you're doing a bit better now. The GetObjectData method on Person is

                        public void GetObjectData(SerializationInfo info, StreamingContext context)
                        {
                    
                            info.AddValue("Name", name);
                    
                        }
                    

                    and on Keycard it is

                        public new void GetObjectData(SerializationInfo info, StreamingContext context)
                        {
                            info.AddValue("Keynumber", mykey);
                    
                        }
                    

                    The base class (Person) is a normal method and the inherited class (Keycard) is marked "new" which means you're breaking the inheritance chain and saying that the two methods may have the same name but they are their own thing. When you serialise your data as Person is the class that is ISerializable that is the class your GetObjectData is called on, the version on Keycard is never called. What you need to do is mark the version on Person as virtual and the one on Keycard as override. That means that even though GetObjectData is being called on Person, the method on Keycard will be called instead as that version overrides the one on Person. Now your keycard version is being called you can then call the version on Person yourself. Person;

                    public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
                    {
                    info.AddValue("Name", name);
                    }

                    Keycard;

                    public override void GetObjectData(SerializationInfo info, StreamingContext context)
                    {
                    base.GetObjectData(info, context);
                    info.AddValue("Keynumber", mykey);
                    }

                    Now when serialisation happens both GetObjectData methods will be called. Your next problem is that when you deserialise Keycard the constructor called is

                        public Keycard(SerializationInfo info, StreamingContext context)
                            : base ("unnamed")
                        {
                            Mykey = (int)info.GetValue("Keynumber", typeof(int));
                        }
                    

                    The problem here (admittedly I did say to code that but I didn't fully understand what you're trying to do) is that your Keycard constructor is called the non-ISerializable constructor on Person;

                    public Person(string name)
                    {
                    this.Name = name;
                    }

                    So the keycard constructor is reading the Mykey value from the SerializationInfo object, but the Person constructor is hard-coding the name to "unnamed", it isn't reading from SerializationInfo. So you need to call the ISerializable constructor on Person instead;

                    public Keycard(SerializationInfo info, StreamingContext context)
                    : base (info, context)

                    1 Reply Last reply
                    0
                    • M Marc Hede

                      Ah of course. Sometimes it surprises me how simple the solution is. I tend to overthink things :-D The only issue now is that I get a

                      System.Runtime.Serialization.SerializationException

                      at

                      Mykey = (int)info.GetValue("Keynumber", typeof(int));

                      Do I need to add Keynumber in my other class file?

                      using System;
                      using System.Collections;
                      using System.Collections.Generic;
                      using System.Linq;
                      using System.Xml.Serialization;
                      using System.IO;
                      using System.Runtime.Serialization.Formatters.Binary;

                      namespace Keycard
                      {
                      class Class1
                      {
                      public static void Main(string[] args)
                      {
                      Keycard k1 = new Keycard("John", 123);

                              Stream stream = File.Open("KeycardData.dat",
                                  FileMode.Create);
                      
                              BinaryFormatter bf = new BinaryFormatter();
                      
                              bf.Serialize(stream, k1);
                              stream.Close();
                      
                              k1 = null;
                      
                              stream = File.Open("KeycardData.dat", FileMode.Open);
                      
                              bf = new BinaryFormatter();
                      
                              k1 = (Keycard)bf.Deserialize(stream);
                              stream.Close();
                              Console.WriteLine(k1.ToString());
                              Console.ReadLine();
                          }
                      
                      }
                      

                      }

                      Richard DeemingR Offline
                      Richard DeemingR Offline
                      Richard Deeming
                      wrote on last edited by
                      #14

                      Make Person.GetObjectData a virtual method. Change Keycard.GetObjectData to override the method instead of shadowing the method, and have it call the base method.

                      [Serializable()]
                      public class Person : ISerializable
                      {
                      ...
                      public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
                      {
                      info.AddValue("Name", name);
                      }
                      ...
                      }

                      [Serializable()]
                      public class Keycard : Person
                      {
                      ...
                      public override void GetObjectData(SerializationInfo info, StreamingContext context)
                      {
                      base.GetObjectData(info, context);
                      info.AddValue("Keynumber", mykey);
                      }
                      ...
                      }

                      Your code will now work. However, you're creating Stream objects, which should be disposed of when you're finished with them. The simplest way to do that is with a using block[^].

                      Keycard k1 = new Keycard("John", 123);
                      BinaryFormatter bf = new BinaryFormatter();

                      using (Stream stream = File.Open("KeycardData.dat", FileMode.Create))
                      {
                      bf.Serialize(stream, k1);
                      }

                      k1 = null;

                      using (Stream stream = File.Open("KeycardData.dat", FileMode.Open))
                      {
                      k1 = (Keycard)bf.Deserialize(stream);
                      }

                      Console.WriteLine(k1);
                      Console.ReadLine();


                      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                      "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups