You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity卡牌游戏开发:List<Card>无法识别派生类属性问题求助

解决基类集合中访问派生类专属属性的问题

你遇到的问题是静态类型检查导致的:List<Card>中的元素编译时被识别为基类Card类型,而基类并没有派生类(如MonsterCard)的专属属性(Health、Power等),所以编译器会报错。这不是对象本身没有这些属性,而是编译器无法在编译阶段确定当前Card实例的具体派生类型。

下面是几种可行的解决方法,按推荐程度排序:

1. 用多态实现(面向设计原则的最优解)

不要直接访问派生类的属性,而是在基类定义抽象/虚方法,让派生类自己实现专属的展示逻辑,完全符合开闭原则。

示例代码:

// 基类定义抽象展示方法
public abstract class Card
{
    public string Name { get; set; } // 公共属性
    public abstract void DisplayDetails();
}

// MonsterCard实现自己的展示逻辑
public class MonsterCard : Card
{
    public int Health { get; set; }
    public int Power { get; set; }
    public string MonsterType { get; set; }

    public override void DisplayDetails()
    {
        Console.WriteLine($"[怪物卡牌] {Name} | 类型:{MonsterType} | 血量:{Health} | 攻击力:{Power}");
    }
}

// LocationCard实现自己的展示逻辑
public class LocationCard : Card
{
    public int EBoost { get; set; }

    public override void DisplayDetails()
    {
        Console.WriteLine($"[地点卡牌] {Name} | 增益:{EBoost}");
    }
}

// DisplayCard类中直接调用统一方法
public class DisplayCard
{
    public void ShowAllCards(List<Card> cards)
    {
        foreach (var card in cards)
        {
            card.DisplayDetails(); // 自动调用对应派生类的实现
        }
    }
}

2. 类型转换与模式匹配(适合简单场景)

如果不需要重构多态,可以在访问前先判断类型并转换,C# 7+支持的模式匹配语法会更简洁。

示例代码:

public class DisplayCard
{
    public void ShowAllCards(List<Card> cards)
    {
        foreach (var card in cards)
        {
            // 模式匹配直接转换为MonsterCard
            if (card is MonsterCard monsterCard)
            {
                Console.WriteLine($"怪物:{monsterCard.Name} | 血量:{monsterCard.Health} | 类型:{monsterCard.MonsterType}");
            }
            // 同理处理LocationCard
            else if (card is LocationCard locationCard)
            {
                Console.WriteLine($"地点:{locationCard.Name} | 增益:{locationCard.EBoost}");
            }
        }
    }
}

也可以用switch表达式简化:

foreach (var card in cards)
{
    var details = card switch
    {
        MonsterCard mc => $"怪物:{mc.Name} | 血量{mc.Health}",
        LocationCard lc => $"地点:{lc.Name} | 增益{lc.EBoost}",
        _ => $"未知卡牌:{card.Name}"
    };
    Console.WriteLine(details);
}

3. 不推荐:在基类添加所有派生类属性

你之前尝试在基类加这些属性的做法不可取,原因是:

  • 破坏封装:基类不需要知道派生类的专属细节
  • 违反开闭原则:新增派生类时必须修改基类
  • 逻辑冗余:比如LocationCard不需要Health属性,会出现无效的空值或默认值

内容的提问来源于stack exchange,提问作者TheAlmightyOneX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 10:16:27