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

C# 10.0自引用泛型变量声明及实现简化疑问

关于自引用泛型IBuilder的两个问题解答

问题1:当前实现是否过于复杂,有无更简洁的实现方式?

自引用泛型是实现强类型Fluent API的常规手段,但如果觉得这种写法冗余,可以根据场景选择以下简化方案:

方案1:放弃强类型自引用,使用非泛型接口

如果你的Builder体系不需要在子类扩展专属的Fluent方法,完全可以去掉泛型约束,直接返回接口本身:

public interface IContextBuilder
{
    IContextBuilder WithName(string name);
    IContextBuilder WithTimeout(int seconds);
    IContext Build();
}

public class DefaultContextBuilder : IContextBuilder
{
    private readonly IContext _context = new Context();

    public IContextBuilder WithName(string name)
    {
        _context.Name = name;
        return this;
    }

    public IContextBuilder WithTimeout(int seconds)
    {
        _context.Timeout = seconds;
        return this;
    }

    public IContext Build() => _context;
}

这种写法最简洁,但缺点是链式调用时只能访问接口定义的方法,无法直接调用子类新增的扩展方法。

方案2:用抽象基类封装通用逻辑

如果需要保留强类型链式调用,同时减少重复代码,可以把泛型约束和通用逻辑抽到抽象基类中:

public abstract class ContextBuilderBase<TContext, TSelf> 
    where TSelf : ContextBuilderBase<TContext, TSelf>
    where TContext : IContext, new()
{
    protected readonly TContext _context = new TContext();

    public abstract TSelf WithName(string name);
    public abstract TSelf WithTimeout(int seconds);

    public TContext Build() => _context;
}

public class DefaultContextBuilder : ContextBuilderBase<Context, DefaultContextBuilder>
{
    public override DefaultContextBuilder WithName(string name)
    {
        _context.Name = name;
        return this;
    }

    public override DefaultContextBuilder WithTimeout(int seconds)
    {
        _context.Timeout = seconds;
        return this;
    }
}

基类负责初始化Context和定义Build方法,子类只需要实现具体的Fluent配置方法,比纯接口的自引用写法更简洁,同时保留了强类型的链式调用能力。

问题2:如何声明IContextBuilder<IContext, IContextBuilder<...>>类型的变量?

这种递归泛型的声明不需要无限嵌套,直接用具体的实现类作为泛型参数即可:

// 直接声明为具体实现类对应的接口类型
IContextBuilder<IContext, DefaultContextBuilder> builder = new DefaultContextBuilder();

因为DefaultContextBuilder实现了IContextBuilder<IContext, DefaultContextBuilder>,所以这个声明是合法的,同时保留了接口的抽象性。

如果使用C# 12及以上版本,还可以通过泛型别名简化声明:

// 定义别名
using IDefaultContextBuilder = IContextBuilder<IContext, DefaultContextBuilder>;

// 使用别名声明变量
IDefaultContextBuilder builder = new DefaultContextBuilder();

如果不想依赖具体实现类,建议回到问题1的方案1,使用非泛型接口声明变量,写法更简洁:

IContextBuilder builder = new DefaultContextBuilder();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 17:52:35