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

如何解决CS0027错误,在NodeListService1构造中避免二次循环添加ID?

初始问题

能否在Test1类的构造函数中,将this.lst字段传递给Test类的构造函数(不将lst字段设为static)?

代码示例:

class Test
{
    internal Test(List<int> lst)
    {
        lst.Add(1);
    }
}

class Test1 : Test
{
    private List<int> lst = new();

    internal Test1() : base(this.lst)
    {

    }
}

更新后的问题

代码

class NodeListService<T> where T : NodeWrapper
{
    private List<T> lst_node = new();
    internal IList<T> ElementsList
    {
        get => this.lst_node.AsReadOnly();
    }

    internal NodeListService(List<Node> lst_ext_node, Func<Node, T> create_node)
    {
        // 遍历列表
        foreach (Node cur_node in lst_ext_node)
        {
            T cur_node_wrapper = create_node(cur_node);
            this.lst_node.Add(cur_node_wrapper);
        }
    }
}

class NodeListService1 : NodeListService<NodeWrapper1>
{
    private IDGenerator id_generator = new();

    internal NodeListService1(List<Node> lst_ext_node) : base
    (
        lst_ext_node,
        cur_node =>
            {
                NodeWrapper1 cur_node_wrapper = new((Node1)cur_node);
                this.id_generator.AddID(cur_node_wrapper.ID);// 不允许这么做
            }
    )
    {
        // 可以这么实现,但会在基类构造函数的循环之后,对节点进行第二次遍历
        foreach (NodeWrapper1 cur_node_wrapper in this.ElementsList)
        {
            this.id_generator.AddID(cur_node_wrapper.ID);
        }
    }
}

class NodeListService2 : NodeListService<NodeWrapper2>
{
    internal NodeListService2(List<Node> lst_ext_node) : base(lst_ext_node, cur_node => new NodeWrapper2((Node2)cur_node))
    {

    }
}

#region Node
// Node、Node1和Node2是外部实现,无法修改
class Node
{
}

class Node1 : Node
{
    internal int ID;

    internal Node1(int id)
    {
        this.ID = id;
    }
}

class Node2 : Node
{
    internal readonly int OtherField;

    internal Node2(int other_field)
    {
        this.OtherField = other_field;
    }
}
#endregion

#region NodeWrapper
// NodeWrapper1和NodeWrapper2是我为Node1和Node2分别创建的包装类
// 它们继承自NodeWrapper,因为两者都需要访问NodeValue字段
class NodeWrapper
{
    protected readonly Node NodeValue;

    internal NodeWrapper(Node cur_node)
    {
        this.NodeValue = cur_node;
    }
}

class NodeWrapper1 : NodeWrapper
{
    internal readonly int ID;

    #region 构造函数
    internal NodeWrapper1(Node1 cur_node) : base(cur_node)
    {
        this.ID = cur_node.ID;
    }
    #endregion
}

class NodeWrapper2 : NodeWrapper
{
    internal readonly int SomeOtherField;

    internal NodeWrapper2(Node2 cur_node) : base(cur_node)
    {
        this.SomeOtherField = cur_node.OtherField;
    }
}
#endregion

class IDGenerator
{
    private int counter = 0;
    private HashSet<int> hs_used_id = new();

    // 如果要创建新的Node1(及其对应的NodeWrapper1),需要生成递增的ID
    internal int GetNewID()
    {
        while (hs_used_id.Contains(this.counter++)) ;
        return this.counter;
    }

    internal bool AddID(int id) => hs_used_id.Add(id);
}

场景与问题说明

存在外部不可修改的Node、Node1、Node2类,需为其创建对应的NodeWrapper1、NodeWrapper2包装类,以及NodeListService1、NodeListService2类分别管理这些包装类的列表。NodeWrapper1类包含ID字段,需将该字段值读取并添加至NodeListService1类的id_generator字段(IDGenerator类实例)中的已用ID列表。

NodeListService基类在构造函数中通过create_node委托循环创建包装类并加入内部列表。目前在NodeListService1的构造函数中,只能通过二次遍历ElementsList属性获取的包装类节点来添加ID;尝试将NodeListService1的id_generator字段传递给create_node委托时,会触发CS0027错误。

请问是否存在无需二次循环即可将已用ID添加至id_generator的实现方法?


解决方案

方法一:提前初始化id_generator并通过闭包传递

先在NodeListService1的公开构造函数外初始化id_generator,再通过私有构造函数将其传入闭包,这样就能在创建NodeWrapper1时直接调用AddID,避免二次遍历。

修改后的NodeListService1代码:

class NodeListService1 : NodeListService<NodeWrapper1>
{
    private readonly IDGenerator id_generator;

    internal NodeListService1(List<Node> lst_ext_node) 
        : this(lst_ext_node, new IDGenerator())
    {
    }

    // 私有构造函数,接收提前初始化的IDGenerator
    private NodeListService1(List<Node> lst_ext_node, IDGenerator generator) 
        : base(lst_ext_node, cur_node => 
          {
              NodeWrapper1 wrapper = new((Node1)cur_node);
              generator.AddID(wrapper.ID);
              return wrapper;
          })
    {
        this.id_generator = generator;
    }
}

方法二:扩展基类构造函数,添加回调委托

如果允许修改基类NodeListService,可以新增一个构造函数,除了create_node外,再添加Action<T>类型的回调,用于在创建包装类后执行额外操作(比如添加ID)。

修改后的基类和NodeListService1:

class NodeListService<T> where T : NodeWrapper
{
    private List<T> lst_node = new();
    internal IList<T> ElementsList => lst_node.AsReadOnly();

    // 保留原有构造函数
    internal NodeListService(List<Node> lst_ext_node, Func<Node, T> create_node)
        : this(lst_ext_node, create_node, _ => { })
    {
    }

    // 新增构造函数,支持创建后的回调
    internal NodeListService(List<Node> lst_ext_node, Func<Node, T> create_node, Action<T> postCreateAction)
    {
        foreach (Node cur_node in lst_ext_node)
        {
            T wrapper = create_node(cur_node);
            lst_node.Add(wrapper);
            postCreateAction(wrapper); // 执行回调
        }
    }
}

class NodeListService1 : NodeListService<NodeWrapper1>
{
    private IDGenerator id_generator = new();

    internal NodeListService1(List<Node> lst_ext_node) 
        : base(lst_ext_node, 
               cur_node => new NodeWrapper1((Node1)cur_node),
               wrapper => id_generator.AddID(wrapper.ID))
    {
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 03:43:11