【问题标题】:Check and compare two objects检查和比较两个对象
【发布时间】:2020-03-27 14:50:00
【问题描述】:

我有一个 Buildable 抽象类,它继承了 House 和 Road 类。

我正在尝试对包含房屋和道路的可构建对象数组进行分类。

我知道我可以检查一个对象是否是这样的 Road:f(myBuildables[i] is Road) 并且它工作得很好,但是出于可伸缩性的原因,我希望有一个包含从 Buildable 继承的类的数组。我尝试了一些东西,但显然它不起作用:class[] inheritTypes = { House, Road }

我也尝试过使用 Types[] buildableTypes = { typeOf(Hosue), typeOf(Road) } 类型的数组,但我无法比较类型,因为 typeOf(myBuildables[i]) 总是返回可构建类型。

【问题讨论】:

  • 试试Buildable[]?
  • 应该如何使用?
  • 你要处理多少个可构建继承者?只是一个警告:你不会绕过类型检查。充其量你可以得到别人的代码为你做这项工作。
  • 有一个实际上相同的问题,但对于 Winforms。抽象类是“抽象问题”。我可以将您链接到我的答案:stackoverflow.com/a/59116927/3346583 |正确答案实际上取决于您将要对这些实例做什么,一旦您知道它们的类型是什么。
  • 好的。即使是改进的开关,20 也确实太多了。这将需要Dictionary<type, delegate>。再次强调一下:这真的取决于你在施放它们之后打算对这些实例做什么。 |像进展蜱一样的东西?这可以通过他们从 Buildable 继承或从接口获取的函数来完成。画?同样的交易。在没有向我们展示你打算如何处理至少这两个的情况下,这就是我现在能给你的所有信息。

标签: c# unity3d inheritance types compare


【解决方案1】:

给定

public abstract class Buildable{}

class Road : Buildable{}
class House : Buildable{}

您可以执行以下操作

List<Buildable> buildables = new List<Buildable>();
buildables.Add(new House());
buildables.Add(new Road());
buildables.Add(new House());

foreach(var item in buildables)
{
    if(item is House)
    {
        Console.WriteLine("House");
    }
    if (item is Road)
    {
        Console.WriteLine("Road");
    }
}

或者在 C# 8.0 中,您可以进行高级模式匹配,如下所示:

abstract class Buildable { 
    public bool Damage;
}

class Road : Buildable { }
class House : Buildable { }

与模式匹配:

List<Buildable> buildables = new List<Buildable>();
buildables.Add(new House());
buildables.Add(new Road());
buildables.Add(new House{  Damage = true });

foreach (var item in buildables)
{
    switch (item)
    {
        case House damageHouse when damageHouse.Damage:
            Console.WriteLine("House Damaged");
            break;
        case House house:
            Console.WriteLine("House");
            break;
        case Road road:
            Console.WriteLine("Road");
            break;
        case Buildable _:
            Console.WriteLine("Default");
            break;
    }

}

【讨论】:

    【解决方案2】:

    你应该使用object.GetType():

    myBuildables [I] .GetType ();
    

    这是一个示例代码:

     class Program
        {
            abstract class Buildable
            {
                public string Name { get; set; } = string.Empty;
            }
    
            class Home : Buildable{}
    
            class Roard: Buildable{}
    
            static void Main(string[] args)
            {
                List<Type> listTypes = new List<Type>()
                {
                    typeof(Home),
                };
    
                List<Buildable> listBuildable = new List<Buildable>()
                {
                    new Home(){Name = "home 1"},
                    new Home(){Name = "home 2"},
                    new Home(){Name = "home 3"},
                    new Roard(){Name = "road 1"},
                    new Roard(){Name = "road 2"},
                    new Roard(){Name = "road 3"},
                };
                foreach(var item in listBuildable)
                {
                    var itemType = item.GetType();
                    Console.WriteLine("Buildable name = " + item.Name);
                    Console.Write("item typeof" + itemType.ToString());
    
                    if (listTypes.Find(o => o.Equals(itemType)) != null)
                        Console.WriteLine(" - Type isset in list");
                    else
                        Console.WriteLine(" - Unknown type");
    
                    Console.WriteLine();
    
                }
                Console.ReadLine();
            }
        }
    

    结果:

    可构建的名称 = 家 1 item typeofConsoleApp1.Program+Home - 在列表中输入 isset

    可构建的名称 = home 2 item typeofConsoleApp1.Program+Home - 在列表中输入 isset

    可构建的名称 = home 3 item typeofConsoleApp1.Program+Home - 在列表中输入 isset

    可建造名称 = 道路 1 item typeofConsoleApp1.Program+Roard - 未知类型

    可建造名称 = 道路 2 item typeofConsoleApp1.Program+Roard - 未知类型

    可建造名称 = 道路 3 item typeofConsoleApp1.Program+Roard - 未知类型

    【讨论】:

    • 多态代码在这里没有帮助而不是做这么多的反射吗?
    • @Mr.Young 你到底是什么意思?
    • 反射是一个后备。如果没有其他东西可以满足您的需求,您就可以使用它。如果您有一个基于反射的默认值,那么您确实应该采用适当的、非基于反射的方法。
    • @Christopher 我知道,但我建议了一个要求的解决方案:...但出于可扩展性的原因,我想要一个包含从 Buildable 继承的类的数组
    • Roard 和两个 rs?
    【解决方案3】:

    is 检查实例的等效功能是 Type.IsAssignableFrom (docs)。

    在你的情况下:

    if (typeof(House).IsAssignableFrom(obj.GetType()))
    {
    //obj is a house
    }
    

    因此,您可以将类型保存在数组中,然后根据该数组的内容动态做出决定。

    【讨论】:

    • 值得注意的是,如果您这样做,您的设计可能存在缺陷,并且可能有更好的方法。例如创建一个名为DoYThing() 的抽象方法,House 实现它,Road 留下一个空存根(另一个方法DoXThing()House 作为存根留下,Road 实现)。接口和抽象类的全部意义在于您不应该需要永远对其特定类型执行强制转换。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-02
    • 2014-01-26
    • 2012-08-17
    • 2014-03-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多