C# explicit casting to derived classes

It is common in games to have a lot of classes with both shared and specific implementations, sometimes you want to run specific logic if it is of a specific type.

As an example you have a input script which detects when you click on a game object, if the game object has a component which is of a certain type then you pass the component to other classes which require it such as the UI, the UI now might need to do run certain logic depending on what the derived class is.

Generic code example:

public interface IEntity {

    // related properties and methods

}

public class Human : IEntity {

    // related properties and methods

}

public class Monster : IEntity {

    // related properties and methods

}
public void SomeMethod(IEntity entity) {

    // Alternative to using IS then cast.
    Monster monster = entity as Monster;
    if(monster != null) {
        monster.DoMonsterSpecificMethod();
    }

}

The general view on stackoverflow is that in C# it is consider it bad design, but that might not necessarily be the same view in game development.

  1. Is it considered bad practice to pass around interfaces or base classes, check the type then cast them to their concrete or derived class?
  2. If it is poor design, what are the better alternatives?

When using interface logic a specific implementation is achieved in the concrete implementation of an interface method , not in a unique method name on the class itself. It seems you are only using the interface for datatyping?

Its really bad practice to cast objects downwards. Sometimes its necessary but in general thats a hint for a bad design.

If you’re using interfaces you should keep them small and simple with just specific methods. Than you don’t have to cast downwards.

For example

interface Attacker
{
    void Attack();
}

public class SwordFighter : Attacker
{
    public void Attack()
    {
    }
}

public class BowFighter : Attacker
{
    public void Attack()
    {
    }
}

Maybe you’re thinking: Ok each attacker should also be moveable, so adding a Move method to the interface is a good idea. Than you start to mix things and sometime you come to the point when you need to downcast.

As you already identified in a different environment ( game development ) specifically Unity, you have to make best with the tools and structures at hand. Unity is a component driven architecture and GetComponent method does not understand interfaces. Base/abstract classes are you friend here ( one level of inheritance is not evil ) , then there is also a tag system to make use of for filtering …etc…

Not that I have personally found the holy grail balance in when to use what in Unity but I can say a pure OOP outlook of how to do things is not always fitting the task at hand, another example is the GUI inspectors for Monobehaviours . Which is better … to sniff for another type of component via code or to inject the dependency via drag and drop both have pro and con arguments.

Just thought I would add this as more food for thought.

I think my question may have been slightly misunderstood, it wasn’t anything to do with interfaces as in the code example you can easily change the interface to abstract class and implementation to inheritances.

I’ll try to reword the question.

If you have a group of classes which represent different things, but are derived from the same class, but depending on what it represents may get used differently which may even required accessing the derived classes specific properties and methods, how is the best way to achieve this?

Examples:

You send a message across the network, all the messages are derived from abstract class NetworkMessage, each different type of message needs its own implementation, but each NetworkListener has a method for OnMessageRecieved(NetworkMessage message) which is the base class, in order to get the additional information, its required to be explicitly cast (unboxed).

public class NetworkMessage {
    public int id;
}

public class MoveCommand : NetworkMessage {
    public Vector3 position;
    public List<int> units;
}

public class SomeClass : Monobehaviour, NetworkListener {

    public void OnNetworkMessageRecieved(NetworkMessage message) {
        if(message is MoveCommand) {
            // Do move logic
        }
    }
}

Another example could be selecting units on a map, you might pass around the base class to other systems, but at some stage depending on what you have selected you might need to do something more specific found in derived class.

If using interfaces or inherited classes in this manner is considered bad practice, what is the better alternative?

In that case use method overloading. So each derived class uses its own implementation of the method. You can also make the method abstract so that each derived class has to override the method.

public class NetworkMessage {
    public int id;

    public virtual void DoSomething() {}
}

public class MoveCommand : NetworkMessage {
    public Vector3 position;
    public List<int> units;

    public override void DoSomething() {
        // Do the moving
    }
}

public class SomeClass : Monobehaviour, NetworkListener {
    public void OnNetworkMessageRecieved(NetworkMessage message) {
        message.DoSomething();
    }

}

As THoeppner displayed is correct.

You could also have additional data added to notifications like commands for instance as is seen in many event systems. You dont only need to derive alternate behaviour instructions via Datatypes and overloaded methods otherwise every single new behaviour requires a new type of subclass.

This is subjective to preference… many strictly proper OOP structures have an ill side effect of resulting in verbose code unfortunately.

What about if you just wanted the data? e.g. position and units. You may not even need any field or method it contains, you just want to do something IF it is of a specific derived type e.g EndTurnCommand.

Another way to word the question would be how is a good way to pass around a lot of different object types all under one object then act on them depending on what they originally were.

If you’ve got base-class specific behaviour why don’t you use virtual methods? That’s specifically what they’re for.

The approach you’re taking ensures that a huge amount of the code that you write needs to be written with explicit knowledge of a code hierarchy elsewhere. You’re not using a class hierarchy to encapsulate derived behaviour, instead you’re scattering it all over the place. It’s a nightmare for maintainability, and it’s probably quite error prone, and it’s throwing away the benefits of things like type safety. To use a metaphor, you’re using a hammer to bash a screw.

As an alternative, why not provide a “DoLogic()” abstract method in NetworkMessage? Each type of NetworkMessage then has to implement a concrete version, and your SomeClass no longer needs a huge stack of if (…) { } else if (…)… bits of code. It just calls the high-level “DoLogic()”, and the internals of your class structure will work in your favour instead of against it.

In the example of the network message, the message is just a simple data class which doesn’t actually perform any logic.

Also something you want may be specific to particular derived class for example, you select eg you select a entity (eg could be a structure, environmental object, unit, enemy unit etc) the GUI lets say wants to only display the skill bar if its a unit / enemy unit etc. The UI doesn’t necessarily want to make the entity perform any logic.

You could just pass the gameobject through then do getcomponent but that would be surely slower than unboxing?

Essentially whats a good design for being able to handle not know what something is specifically at runtime, but checking then handle accordingly.

I still kind of feel like my question is being misunderstood but perhaps its me misunderstanding the answers :wink:

That’s what it is now, but you’re asking us what to do differently, and that’s one suggestion. If you’ve got behaviour specific to a given class then best practice is to have it in that class. Otherwise you have to spaghetti it around and have to start infecting other classes with explicit knowledge of how that class or class structure works.

In the example of the GUI showing different stuff based on what unit is selected, I’d personally consider either having those as properties of a single unit class, or having the unit class have simple logic that informs that GUI that something changed and then letting the GUI handle it. After all, I wouldn’t expect a unit to make decisions about what the GUI shows because, again, that’s spaghetti-ing the functionality around.

For instance, selecting the unit might call a generic “Select” method. That method might fire an “OnSelected” event. Your GUI listens for OnSelected events and responds to them accordingly.

1 Like

The short answer is to use polymorphism where it’s appropriate and to avoid the situation any other time. It is absolutely something that can be designed for, but you will have to change more than one thing in your design to make it work. It’s a holistic approach question, not a specific case question.

Thanks for the discussion.

Let say you also have buildings that can be selected as well, would you use OnSelected event for both then have the GUI determine which was selected and act accordingly or a separate one for each then listen to both.

Also lets say you have your unit selected, you then right click on another entity, if it is a structure you want to occupy it, if its an allied unit follow, if it is a enemy unit attack etc. I would have thought passing the entity to the unit then having the unit determine what it is and act accordingly be straightforward, understandable and relatively cheap, how you would approach it?

How is a building different to a unit?

There are no one-shot correct answers to these things. Design is about problem solving, and problem solving is about understanding the whole of the thing and the context it is within.

I would start by figuring out the kinds of things I wanted all of my different entities to be able to do. Then I’d figure out the data they each needed to be able to do it. Then I’d shuffle the whole lot around so that like things are somehow grouped together, but in the simplest way possible, with generic methods and data that cover as much as possible. I’d possibly try that a few times to see how things ultimately fit best.

You’re trying to design a system, but you’re asking relatively low level implementation questions to do it. You’re asking things like “what happens when I click…” instead of “what interactions does my system need to support” and working down from there.

Here’s the answer (to this particular question at least) about casting downwards for network messages to get your custom data: https://docs.unity3d.com/ScriptReference/Networking.NetworkMessage.ReadMessage.html

Probably a misnomer in this case since NetworkMessage didn’t exist in 2013. Hilarious coincidence!

1 Like

I’m going to necro this thread worse than it already has been, because I ran into a similar situation and stumbled across it.

In my situation:

I have a C# server, not unity.
In a shared assembly (shared between Unity and the server), it has NetMessage defined, a base class. This is shared so both the client and server know about certain shared network messages.

One of its derived classes is LoginRequest. LoginRequest has two properties, the login id and the password.
When the client wants to login to the server, it creates and sends a new LoginRequest(login, password) to the server.

Now, the server receives the network data, and has to create a loginrequest message for login handling by the server.

        private static NetMessage ReadMessage(NetPeer peer, NetDataReader reader)
        {
            short rawMessageType = reader.GetShort();
            MessageType messageType = (MessageType)rawMessageType;
            NetMessage message;
            switch (messageType)
            {
                case MessageType.None:
                    message = new NullMessage();
                    break;

                case MessageType.LoginRequest:
                    message = new LoginRequest();
                    break;
                default:
                    message = new NullMessage();
                    CLog.Log($"Unknown message type {rawMessageType} received from {peer.EndPoint}");
                    break;
            }

            message.Read(reader);
            return message;
        }

so it creates the concrete message type, and calls .Read() to actually read in the byte data from the network stream or whatever, and populate an actual login message. But this function returns it as a NetMessage, NOT a LoginRequest.
Why? I want to handle the Read function for all, in one place, instead of having to handle the serialization in each case statement.

When it returns it, I need to actually handle the login request.
This is where I think one of the above posters is touching on.
So I have a NetMessage now, that is actually a base type of some derived type. So now I want to actually do the login work.

          switch (message.Type)
            {
                case MessageType.None:
                    break;
                case MessageType.LoginRequest:
                    HandleLoginRequest(peer, (LoginRequest) message);
                    break;

So now I have to cast it BACK to a LoginRequest, because this is on the server. I do NOT want to have the actual login handling code in the LoginRequest, because that is available to the client. I want to call a method on the server, and actually pass it a LoginRequest, so it can access the login id and password.

I don’t see how I could have a generic way to handle DoWork() on the NetMessages, unless I want to have both messages defined, one for the client and one for the server. That’s the only way I could see to handle that. The client one is basically a data class, the server one actually has the login handling code.

So…a viable way of handling it, personally I don’t care for the duplication and so far I feel just downcasting is fine in this case. These messages only transport data, they don’t handle processing the results.

Usually when you have a server and a client… you won’t have the same actual libraries on both for such things.

These are called ‘Data Contracts’, the type that is transferred between client and server are pure data, very limited on the code.

Check out something like WCF (windows communication foundation, it actually uses the terminology DataContract). When you define web methods on your WCF interface, then host the web service, a client can request from the server the data contract information. In doing so it can build its own data types that serialize to what the server expects.

They’ll often be named the same thing… but are distinct class types on the client side.

Any implementation, non-data, is then implemented apart from these datacontracts.

You might have a ‘LoginRequest’ and a ‘LoginRequestResolver’ class distinct from one another, one for data, the other for handling that data.

Yeah, I get the WCF environment, however I’m using a different means of communications.

In this case, the only reason I see for having two different ones are 1. To avoid downcasting, and 2. to put the logic to handle a login request inside the message, which I personally wouldn’t choose to do anyway.
It seems if I am just sending a login request from the client to the server, why not let both know about the login request message type if all it is is a message envelope, a data class. I’d prefer to have some other object in place to handle the actual login resolution.