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

能否将Func<T>泛型设为可动态赋值方法的属性?C#卡牌类疑问

卡牌游戏Card类效果属性的泛型实现问题

我正在开发一款卡牌游戏,想给Card类添加独特的卡牌效果。计划给这个类加一个Effect属性,既能在构造函数里初始化,也能后续通过赋值器修改。现在的问题是不确定这个Effect方法该用什么返回类型:用Action的话没法返回值,但测试的时候需要返回Card、List、玩家或者卡组对象来验证效果。

作为C#新手,我对泛型的用法搞不清楚:目前用Func实现了读写,但不确定object能不能接收所有类型的返回值(比如那些没继承自object的类);一开始还试了定义无类型的Func<>,以为能返回非空类型,结果明显错了。


现有实现代码

using System;
[System.Serializable]

public class Card
{
  public int Id { get; set; }
  public string Title { get; set; }
  public int Cost { get; set; }
  public int Power { get; set; }
  public string Description { get; set; }
  public Func<object> Effect { get; set; }
  
  public Card()
  {

  }

  public Card(int id, string title, int cost, int power, string description, Func<object> effect)
  {
    Id = id;
    Title = title;
    Cost = cost;
    Power = power;
    Description = description;
    Effect = effect;
  }
}

最初的错误尝试代码

private Func<> effect;

public Func<> Effect
{
  get { return effect; }
  set { effect = value; }
}

解决思路

  1. 关于object的疑问:C#里所有类型都直接或间接继承自object,所以用Func可以接收任何返回值,测试时只需要把返回的object强制转换为对应的类型就行,比如:
    // 假设Effect返回的是Card类型
    Card result = (Card)myCard.Effect();
    

    但这种方式需要手动强转,容易出现类型转换错误,适合快速验证但不够优雅。

    1. 用泛型Card实现类型安全:如果想让Effect的返回类型更明确,避免强转,可以把Card类改成泛型类:
    using System;
    [System.Serializable]
    
    public class Card<T>
    {
      public int Id { get; set; }
      public string Title { get; set; }
      public int Cost { get; set; }
      public int Power { get; set; }
      public string Description { get; set; }
      public Func<T> Effect { get; set; }
      
      public Card() {}
    
      public Card(int id, string title, int cost, int power, string description, Func<T> effect)
      {
        Id = id;
        Title = title;
        Cost = cost;
        Power = power;
        Description = description;
        Effect = effect;
      }
    }
    

    使用的时候就可以指定返回类型:

    // 返回Card类型的卡牌
    Card<Card> drawCard = new Card<Card>(1, "抽卡", 1, 0, "抽一张卡", () => new Card());
    // 返回List<Card>类型的卡牌
    Card<List<Card>> drawThreeCards = new Card<List<Card>>(2, "三连抽", 2, 0, "抽三张卡", () => new List<Card> { new Card(), new Card(), new Card() });
    

    这种方式类型安全,测试时不需要强转,但缺点是同一张卡牌不能同时返回不同类型的结果,如果有这种需求,泛型就不太适用。

    1. 用自定义结果类统一返回类型:如果卡牌效果可能返回多种类型,可以定义一个包含所有可能返回值的类,让Effect返回这个类:
    public class CardEffectResult
    {
      public Card SingleCard { get; set; }
      public List<Card> CardList { get; set; }
      public Player Player { get; set; }
      public Deck Deck { get; set; }
      // 其他可能的返回类型
    }
    
    // 修改Card类的Effect属性
    public Func<CardEffectResult> Effect { get; set; }
    

    使用时根据效果设置对应的属性:

    Card drawCard = new Card(1, "抽卡", 1, 0, "抽一张卡", () => new CardEffectResult { SingleCard = new Card() });
    

    这种方式统一了返回类型,也能支持多种结果,适合复杂的卡牌效果场景。

    1. 关于无类型Func<>的错误:Func是泛型委托,必须指定类型参数,没有无类型的Func<>,所以之前的写法会编译错误,这是C#语法的要求,必须明确委托的返回类型(以及参数类型,如果有的话)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 05:58:41