返回特定派生类型的对象列表

时间:2018-05-08 01:31:06

标签: c# unity3d

我应该先说明这将在Unity中实现,所以我可以从那里使用一些函数和类名,但是这里有:

我有一个关于我的游戏中可能的项目类型的类,它将存储在JSON文件中:

public class Item
{
    //Properties galore
}

public class Weapon : Item
{
    //All my weapon stats
}

public class Projectile : Weapon
{
    //All my projectile weapon stats
}

所以现在我可以提供一堆统计数据和武器。例如,我的播放器的当前广告资源存储在列表中:

List<Item> playerInventory = new List<Item>();

//And then I go on and add my inventory items from a stored file, etc.

太可爱了,现在我的玩家有一个库存。好极了。不幸的是,我正在努力想办法获得JUST Weapons或JUST Projectile Weapons的清单。我可以在我的JSON文件中添加一个“type”参数,该文件包含每个武器的默认值等,但似乎C#有办法做一些聪明的事情,如

List<Weapon> weaponList = new List<Weapon>();

foreach(Item<Weapon> i in playerInventory)
{
   weaponList.Add(i);
}

我知道,我知道,这根本不对,但希望你明白我的意思。它当然不是那样,但我认为必须有一种方法可以相对轻松地将物品清单变成新的武器清单。

感谢您提供的任何帮助!

3 个答案:

答案 0 :(得分:1)

对于您的用例,您不能使用OfType,因为它使用is运算符检查对象的类型(返回继承树中的所有对象)< / p>

我建议你写一个扩展方法

public static class ListExtensions
{
    public static IEnumerable<TType> IsTypeOf<TType>(this IEnumerable input)
        where TType : class
    {
        foreach (object o in input)
        {
            if (o.GetType() == typeof(TType)) // take note of this, don't use is
            {
                yield return (TType)o;
            }
        }
    }
}

如何使用

var playerInventory = new List<Item>();

playerInventory.Add(new Weapon());
playerInventory.Add(new Weapon());
playerInventory.Add(new Weapon());
playerInventory.Add(new Weapon());
playerInventory.Add(new Projectile());
playerInventory.Add(new Projectile());

// player inventory should have 4 weapons
playerInventory.IsTypeOf<Weapon>().Should().HaveCount(4);
// player inventory should have 2 projectiles
playerInventory.IsTypeOf<Projectile>().Should().HaveCount(2);

希望它有所帮助。

答案 1 :(得分:-1)

你可以使用linq:

来做到这一点
List<Item> inventory = new List<Item>();
// Fill inventory with items of different type.

List<Weapon> weapons = inventory.Where(item => item.GetType() == typeof(Weapon)).Cast<Weapon>().ToList();
List<Projectile> weapons = inventory.Where(item => item.GetType() == typeof(Projectile)).Cast<Projectile>().ToList();

确保添加using System.Linq;才能正常工作。

答案 2 :(得分:-1)

您可以使用LINQ的OfType方法过滤列表。这也会自动将结果转换为正确的类型。

var weapons = inventory.OfType<Weapon>();
var projectiles = inventory.OfType<Projectile>();

请注意,您的对象模型表明Projectile是一种武器(这是继承关系的意思)所以在我的示例中,weapons也将包含射弹。

如果您希望排除某些内容(例如,获取所有非弹丸的武器列表),您可以使用额外的Where子句进行特殊过滤。

var nonProjectileWeapons = inventory
    .OfType<Weapon>()
    .Where
    (
        weapon => !(weapon is Projectile) 
    );

在所有情况下,上述内容都会返回IEnumerable<Weapon>,这是您通常需要的。如果您需要实际的具体List,只需将ToList()添加到最后。

List<Weapon> nonProjectileWeapons = inventory
    .OfType<Weapon>()
    .Where
    (
        weapon => !(weapon is Projectile) 
    )
    .ToList();

当然,如果您只想要特定具体类Weapon的实例(假设它具体 - 它可能应该是抽象的),您可以直接比较where子句中的类型。为了完整性,我会给你一个例子,但我强烈建议你重新审视你的对象模型,如果你发现自己做这样的事情。如果射弹武器不属于武器清单,则不应具有继承关系;也许你需要在你的模型中使用其他一些概念 - 例如,也许武器和弹箭武器都应该从BaseWeapon继承,但彼此之间没有继承关系。

无论如何,这里是。

List<Weapon> unspecializedWeapons = inventory
    .OfType<Weapon>()
    .Where
    (
        weapon => weapon.GetType() == typeof(Weapon) 
    )
    .ToList();
相关问题