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

如何解决TargetManager实例化时的CS0266类型转换错误?

解决TargetManager实例化时的CS0266类型转换错误

问题场景

我定义了如下两个接口:

public interface ITargetManager: ITargetManager<TargetManager, Target>
{

}

public interface ITargetManager<TSelf, T>
   where TSelf : TargetManager<TSelf,T>
   where T : Target
{
    int Prop1 { get; }
    string Prop2 { get; }
    int? Prop3 { get; }
    string Prop4 { get; }

    T Build();
    void Update(T target);
    TSelf WithProp1(int value);
    TSelf WithProp2(string value);
    TSelf WithProp3(int? value);
    TSelf WithProp4(string value);
}

接着实现了继承该接口的抽象类:

public abstract class TargetManager<TSelf, T>
   : ITargetManager<TSelf, T>
    where TSelf : TargetManager<TSelf, T>
    where T : Target
{
    private int prop1;
    private string prop2;
    private int? prop3;
    private string prop4;
    private static ConcurrentDictionary<Type, MethodInfo> dic = new();
    public TargetManager(T? target = null)
    {
        if (target == null) return;

        WithProp1(target.Prop1);
        WithProp2(target.Prop2);
        WithProp3(target.Prop3);
        WithProp4(target.Prop4);
    }
    public int Prop1 => prop1;

    public string Prop2 => prop2;

    public int? Prop3 => prop3;

    public string Prop4 => prop4;

    public TSelf WithProp1(int value)
    {
        prop1 = value;
        return this;
    }

    public TSelf WithProp2(string value)
    {
        prop2 = value;
        return this;
    }

    public TSelf WithProp3(int? value)
    {
        prop3 = value;
        return this;
    }

    public TSelf WithProp4(string value)
    {
        prop4 = value;
        return this;
    }

    public T Build() => (T)Activator.CreateInstance(typeof(T), this)!;

    public void Update(T target)
    {
        var methodInfo = dic.GetOrAdd(typeof(T), getUpdateMethodInfo);
        methodInfo.Invoke(target, new object[] { this });
    }

    private static MethodInfo getUpdateMethodInfo(Type optionType)
    {
        var types = getInheritanceHierarchy(typeof(T));
        var methods = typeof(T).GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(mi => mi.Name == "Update");
        return types.Join(
            methods, t => t.Name,
            mi => mi.DeclaringType.Name,
            (t, mi) => mi)
            .First();

    }

    private static IEnumerable<Type> getInheritanceHierarchy(Type type)
    {
        for (var current = type; current != null; current = current.BaseType)
        {
            yield return current;
        }
    }

    public static implicit operator TSelf(TargetManager<TSelf, T> builder)
    {
        return (TSelf)builder;
    }
}

最后实现了继承该抽象类的具体类:

public class TargetManager : TargetManager<TargetManager, Target>
{
    public TargetManager(Target? target = null) : base(target)
    {

    }
}

尝试通过sutManager = new TargetManager();实例化该具体类时,出现如下错误:

Severity Code Description Project File Line Suppression State
Error CS0266 Cannot implicitly convert type 'BuilderTest.TargetManager' to 'BuilderTest.ITargetManager'. An explicit conversion exists (are you missing a cast?) BuilderTest C:\Users\S.monzavi\source\repos\BuilderTest\BuilderTest\UnitTest1.cs 16 Active

解决方案

原因分析

具体类TargetManager仅继承了泛型抽象类TargetManager<TargetManager, Target>,该抽象类实现的是泛型接口ITargetManager<TargetManager, Target>。非泛型接口ITargetManager虽然继承了泛型版本,但具体类并没有显式实现这个非泛型接口,因此编译器无法自动将具体类实例隐式转换为ITargetManager类型。

解决方法

方法一:让具体类显式实现非泛型接口

修改具体类的定义,添加ITargetManager接口实现:

public class TargetManager : TargetManager<TargetManager, Target>, ITargetManager
{
    public TargetManager(Target? target = null) : base(target)
    {

    }
}

这样编译器就能识别具体类与非泛型接口的继承关系,允许隐式转换。

方法二:调整变量声明类型

如果不需要使用非泛型接口ITargetManager,可以直接将变量声明为具体类类型或泛型接口类型:

// 声明为具体类类型
TargetManager sutManager = new TargetManager();

// 或者声明为泛型接口类型
ITargetManager<TargetManager, Target> sutManager = new TargetManager();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:33:27