C# : Override property type in a derived class

Hello everybody, during the development of our multiplayer game, we have been facing of a big problem : How can we easely override a property type in a derived class ?

I browsed the web a long time whitout finding a good solution. The best one i tried was to use generic type. It’s ok only if you have one property to override, but if you have more than one, it will become fastly hard to maintain and you code will be much complicated.

So, i found my own solution. We’ll use the “new” keyword and polymorphism !

The context

In our game, we have a class base (Building) for our building, and derived class for each building type (BuildingProducer and BuildingPassive). Each building can be upgraded. The level contains specific information depending the type of the building.

We have in our Building class a property Level wich is an instance of the BuildingLevel class. But for each derived class, we need to override the level property type with the specific level class :

The solution

To handle this very particular situation, the solution is to use a combination of the “new” keyword and polymorphism.

The new keyword will hide the property with the same name on the base class.

The base class : Building

public class Building
    {
        #region Properties

        public int Id { get; set; }
        public string Name { get; set; }

        private Level level;
        public Level Level {
            get { return GetLevel(); } //To use polymorphism
            set { SetLevel(value); } //To use polymorphism
        }

        #endregion

        #region Level virtual

        /// <summary>
        /// Useful to use metamorphism and thus, get the child model when call Building properties
        /// </summary>
        /// <returns></returns>
        protected virtual Level GetLevel()
        {
            return level;
        }

        /// <summary>
        /// Useful to use metamorphism and thus, get the child model when call Building properties
        /// </summary>
        /// <returns></returns>
        protected virtual void SetLevel(Level pLevel)
        {
            level = pLevel;
        }

        #endregion
    }

You can see that we are using virtual methods. By doing that, when we call the GetLevel() and SetLevel(), the engine will automatically determine the real type of the objet and call the method in the real class.

Now, we just need to define these methods in the derived classes.

Derived classes : BuildingProducer and BuildingPassive

I only will paste the code of the Producer building because, the code is the same for both classes :

    public class BuildingProducer : Building
    {

        #region Properties

        /// <summary>
        /// Hide the base property, but they both exists
        /// </summary>
        public new LevelProducer Level {
            get { return GetLevel() as LevelProducer; }
            set { SetLevel(value); }
        }
        private LevelProducer level;

        #endregion

        /// <summary>
        /// Useful to use metamorphism and thus, get the child model when call Building properties
        /// </summary>
        /// <returns></returns>
        protected override Level GetLevel()
        {
            return Level;
        }

        /// <summary>
        /// Useful to use metamorphism and thus, get the child model when call Building properties
        /// </summary>
        /// <returns></returns>
        protected override void SetLevel(Level pLevel)
        {
            level = pLevel as LevelProducer;
        }

    }

Usage exemple

You can now use this common property Level defined in the base class with dynamic type returned thanks to polymorphism.

            List<Building> buildings = new List<Building>();

            //Create a new building
            BuildingProducer derivedBuildingProducer = new BuildingProducer
            {
                Id = 1,
                Name = "Test",
                Level = new LevelProducer { Id = 1, Cost = 200, ResourceProducedId = 1, Amout = 20 }
            };
            buildings.Add(derivedBuildingProducer);
            

            //Create a new building
            BuildingPassive derivedBuildingPassive = new BuildingPassive
            {
                Id = 1,
                Name = "Test",
                Level = new LevelPassive { Id = 1, Cost = 200, PassiveIncome = 1 }
            };
            buildings.Add(derivedBuildingPassive);

            //Polymorphism allow to return different type with the same variable name
            Console.Write(buildings[0].Level.GetType().ToString()); //Will return a LevelProducer
            Console.Write(buildings[1].Level.GetType().ToString()); //Will return a LevelPassive

Unity 3D – Best practices for script development

You will find on this page all good practices you must know to keep your scripts easely maintenable and well architectured. This is very important if you plan to work with other programmers

All shorcuts given are available for Microsoft Visual Studio

Scripts

Keep your code well indented

Shortcut : CTRL + K, CTRL + D

A basic of developpement is to keep all your code indented correctly in order to read it more easely.

Keep your code organized with « Regions »

Shortcut : CTRL + K, CTRL + S

I Suggest you to keep your code organized with regions in order to navigate more quickly to where you need to go

You can also roll or unroll the entire pretty simply

Enroll / Roll : CTRL + M, CTRL + M

Always comment your properties or your functions

Just type "///" above the property or the function and Visual Studio will generate automatically the necessary lines 

It’s very important to know for what the property or the function is useful for mostly if you don’t have written it.

Furthermore, the visual studio auto completion will show you all this stuff when you will write your code :

Name all your parameters with a starting “p” letter

When you write a function, i highly suggest you to start all your parameters name with a “p” to clearly and quickly identify what is a class property and what is a parameter.

Always Create an Init() function

A good practice is too use an Init() function wich can take parameters to initialize your component. Beginners put all this stuff directly in the Start() function. 

Having alway an Init() force you and your team to initialize always all your components by the same way. You can then call this function wherever you want.

If your script is auto initialized, you then can call this function on the Start() unity callback :

If you GameObject is instantiated by a spawner for exemple, you just need to call the function after having instantiate the GameObject.

By doing that, you will have a total control of when the Init() function is called !

Names your properties and function clearly

I have seen a lot of projects where programmers give name to their properties who has no sense with the usage of them

It’s really important to give a name wich identify perfectly the usage of your property of function. Here are some examples :

    #region Properties

    /// <summary>
    /// List of connected clients
    /// </summary>
    public List<int> clientsId;

    /// <summary>
    /// Reference to the DarkRift server
    /// </summary>
    public XmlUnityServer serverReference;

    /// <summary>
    /// List of objects handled by the server
    /// </summary>
    public List<NetworkObject> networkObjects;

    /// <summary>
    /// Frame counter on the server
    /// </summary>
    public int currentServerTick = 0;

    #endregion

Keep your functions and properties names correctly written

It’s important to use name convention when you are coding. Here is a complete article about the subject i higly recommands you to read. If you’re lazy, here are the great guidelines :

  1. Don’t use underscore to name your properties / functions
  2. Class and methods start withs a Capital Letter
  3. Properties and variables always starts with a tiny letter
  4. Don’t use abbreviation
Note : This article is continuously updated