【问题标题】:Comparing types in lists比较列表中的类型
【发布时间】:2014-06-28 17:52:32
【问题描述】:

我在 Unity3D Q&A 上问过类似的问题,但没有得到回复。我终于回到了这个项目,但仍然遇到同样的问题。

Link To Unity Question

我已经搜索过了,但我认为我没有找到正确的关键字,因为我仍然没有找到合适的答案。无论如何,我会以不同的方式提出问题,希望有人能指出我正确的方向。

所以下面是我想出的代码,它不是游戏中的实际代码,但它很好地展示了我的问题。

基本上,在 build() 方法中,我想检查两个列表是否都包含相同类型的工具,而无需实际对类型进行硬编码。我不关心具体的工具实例,只关心它是某种类型。目的是我可以创建新工具,而无需修改构建方法来合并这些新类型。

如果有更好的方法,我会全力以赴。

谢谢

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();
        }
    }
}

【问题讨论】:

    标签: c# types unity3d


    【解决方案1】:

    基本上你应该使用Linq从集合中获取所有类型,然后比较结果。

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

    不清楚,您是否也应该只比较仪器的类型或数量。我的回答假设您不关心数量,当您需要两个时,您可以使用一个 spanner 构建。

    -更新

    为了遵守关于子类的要求(Sriram Sakthivel 提到过),您可以检查可用工具类型是否是所需工具类型的子类,以便在需要 Spanner 时可以使用任何 SpecialSpanner

    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方法:

    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;
    }
    

    【讨论】:

    • 不错的答案,但Count() == 0 可以通过!Any 进行优化
    • 为简单起见,我没有将其包含在代码中,但我进行了检查以确保每个工具只能添加一种类型的工具到列表中。抱歉,我不知道这可能会影响答案。
    • 谢谢,目前我不需要它,但很高兴知道。如果可以的话,我会投票。再次感谢。
    • 我实际上最终使用了这个答案,这是我的错,错过了问题中的一些关键细节,但我确实在游戏代码中有子类。
    【解决方案2】:
    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
    }
    

    注意:如果您提供的派生类型多于预期类型,这将失败。例如,如果您提供 SpecialSpannerSpanner 这将不起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-19
      • 1970-01-01
      • 2014-11-12
      • 1970-01-01
      相关资源
      最近更新 更多