Question

I asked a similar question to this over on Unity3D Q&A, but I didn't get a response. I've finally got back round to this project and still have the same issue.

Link To Unity Question

I have searched, but I don't think I've hit the right keywords cause I still haven't found an answer that fits. Anyway, I will ask the question a different way and hopefully someone can point me in the right direction.

So below is the code that I have come up with, it's not the actual code in the game, but it does a good job at showing my problem.

Basically, in the build() method I want to check that both lists each contain the same type of tool, without actually hard coding the type. I don't care about the specific tool instance, just that it is of a certain type. The aim is that I can create new tools without having to modify the build method to incorporate these new types.

If there is a better way to do it I'm all ears.

Thanks

namespace TypeExample
{
    class Tool
    {

    }

    class Spanner : Tool
    {

    }

    class Wrench : Tool
    {

    }

    class Builder
    {
        List<Tool> toolsAvailable = new List<Tool>();

        List<Tool> toolsRequired = new List<Tool>();

        public Builder()
        {
            Spanner spanner = new Spanner();
            Wrench wrench = new Wrench();

            toolsRequired.Add(spanner);
            toolsRequired.Add(wrench);
        }

        public void GiveTool(Tool tool)
        {
            toolsAvailable.Add(tool);
        }

        public void build()
        {
            // if true

            Console.WriteLine("Building");

            // else

            Console.WriteLine("I don't have the tools to build!");

        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Spanner spanner = new Spanner();
            Wrench wrench = new Wrench();

            Builder builder = new Builder();

            builder.GiveTool(spanner);
            builder.GiveTool(wrench);

            builder.build();

            Console.ReadLine();
        }
    }
}
Was it helpful?

Solution

Basicly you should get all the types from collections using Linq and then compair the result.

var toolsAvailableTypes = toolsAvailable.Select(t => t.GetType()).Distinct();
var toolsRequiredTypes = toolsRequired.Select(t => t.GetType()).Distinct();
if (toolsRequiredTypes.Except(toolsAvailableTypes).Any())
{
    //building
}

It is not clear, should you compair only types of instruments or quantity also. My answer assume you don't care about quantity and you can build with one spanner when you require two.

-Update

To comply the requirement about subclasses (Sriram Sakthivel mentioned it) you can check if available tool type is subclass to required tool type so you can use any SpecialSpanner when you need a Spanner

var toolsAvailableTypes = toolsAvailable.Select(t => t.GetType()).Distinct().ToList();
var toolsRequiredTypes = toolsRequired.Select(t => t.GetType()).Distinct().ToList();

if (CanBuild(toolsAvailableTypes, toolsRequiredTypes))
{
    Console.WriteLine("building");
}
else
{
    Console.WriteLine("not enough minerals");
}

CanBuild method:

bool CanBuild(List<Type> toolsAvailableTypes, List<Type> toolsRequiredTypes)
{
    foreach (var requiredType in toolsRequiredTypes)
    {
        bool isAvailable = toolsAvailableTypes.Any(availableType => availableType.IsSubclassOf(requiredType) || availableType == requiredType);
        if (!isAvailable)
        {
            return false;
        }
    }
    return true;
}

OTHER TIPS

var reqdTypes = toolsRequired.Select(x => x.GetType());
var availableTypes = toolsAvailable.Select(x => x.GetType());

if (reqdTypes.Except(availableTypes).Any())
{
    //Something exist in reqdTypes which is not in availableTypes
}

Note:This will fail if you provide more derived type than expected type. For example if you provide SpecialSpanner in place or Spanner this won't work.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top