Sander Koldenhof
Sander Koldenhof

Reputation: 1293

C# Use type of object for casting (to avoid use of switch case)?

I got an abstract Room with multiple child classes. Some of those childs have a property MaximumCapacity. When anything enters a room, I want it to check if that Room has the property, and if so, what it is. I could easily make it using a switch case, but I'd rather not (lots of (repetitive) code).

Only two imporant properties:

This is what I currently have:

// HOW :: Store type of Room in order for me to cast with it.
// My Attempt: 
Type T = CurrentPosition.GetType(); // Get the type of the Room

// The following doesn't work:
// Build-time exception: "T is used as a variable but is a type"
if ((CurrentPosition as T).GetProperty("Capacity") != null) 
{
    // Check capacity and enter Room.
}

I've tried doing the if (int.Parse(CurrentPosition.GetType().GetProperty("MaximumCapacity")) > [number]) But this gives a Can't convert type PropertyInfo to Int. This makes me believe I still have to cast the Room to its clild (I think) in order to check the capacity.

How do I do this?

Upvotes: 0

Views: 110

Answers (3)

ironman
ironman

Reputation: 1066

public abstract class Room
{
    public abstract void BookTheRoom();
}
interface IMaximumCapacity
{
    int MaximumCapacity { get; set; }
}
public class StorageRoom : Room
{
    public override void BookTheRoom()
    {
        Console.WriteLine("Storage room booked to store the items.");
    }
}

public class TwinSharingRoom : Room,IMaximumCapacity
{
    public TwinSharingRoom(int capacity)
    {
        MaximumCapacity = capacity;
    }

    public int MaximumCapacity { get; set; }

    public override void BookTheRoom()
    {
        Console.WriteLine("Twinsharing room booked.");
    }
}

public class SingleSharingRoom : Room, IMaximumCapacity
{
    public SingleSharingRoom(int capacity)
    {
        MaximumCapacity = capacity;
    }

    public int MaximumCapacity { get; set; }

    public override void BookTheRoom()
    {
        Console.WriteLine("Single sharing room booked.");
    }
}

And you can use this as

class Program
{
    static void Main(string[] args)
    {
        var listOfRooms = new List<Room>() { new SingleSharingRoom(1), new StorageRoom(), new TwinSharingRoom(2) };

        foreach(var room in listOfRooms)
        {
            if(room is IMaximumCapacity)
            {
                room.BookTheRoom();
            }
        }
    }
}

Upvotes: -1

Fabio
Fabio

Reputation: 32445

You can do it without type checking.
Change type of MaxCapacity to nullable and make all rooms to have this property.
Then you can simply does room have value of maximum capacity

if (room.MaxCapacity.HasValue)
{
    // do you logic
}

You can do it in more object-oriented way, move logic to the room object to decide is somebody allowed to enter a room

if (room.AllowedFor(player))
{
    // do your logic
}

Then rooms which have MaxCapacity will check for that, rooms which hasn't will always return false.

Upvotes: -1

TheGeneral
TheGeneral

Reputation: 81493

Sounds like a job for an interface and Composition. This way you can check if your rooms support your various functionality

Given

public interface IMaximumCapacity
{
   int MaximumCapacity { get; set; }
}

public class BaseRoom
{

}

public class DerivedRoom : BaseRoom, IMaximumCapacity
{
   public int MaximumCapacity { get; set; }
}

Method

public static bool GetMaximumCapacity(BaseRoom room, out int maximumCapacity)
{
   maximumCapacity = 0;

   if (room is IMaximumCapacity capcityRoom)
   {
      maximumCapacity = capcityRoom.MaximumCapacity;
      return true;
   }

   return false;
}

Usage

if(GetMaximumCapacity(someRoom,out var max)
{
    // yay, do something with max
}

Upvotes: 4

Related Questions