使用'this'作为通用参数,转换问题

Roh*_*est 1 c# generics

这可能吗?当我编译时,我得到一个错误,即使用约束也无法将Component转换为TComponent

public interface IComponent<TKey, TComponent> where TComponent : IComponent<TKey, TComponent>
{
    TComponent Parent { get; }
    void Register(TKey key, TComponent component);
    void RegsiterWith(TKey key, TComponent component);
}

public class Component<TKey, TComponent> : IComponent<TKey, TComponent> where TComponent : IComponent<TKey, TComponent>
{
    private TComponent _parent;

    public void Register(TKey key, TComponent component)
    {
        component.RegsiterWith(key, this);
    }

    public void RegsiterWith(TKey key, TComponent component)
    {
        component.Register(key, this);
    }

    public TComponent Parent { get { return _parent; } }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 8

它失败的原因是因为TComponent实际上可能是其他一些实现IComponent<TKey, TComponent>.只是因为Component实现接口并不意味着没有别的可以:)

这方面的一个方法是更改​​界面:

public interface IComponent<TKey, TComponent> 
    where TComponent : IComponent<TKey, TComponent>
{
    TComponent Parent { get; }
    void Register(TKey key, IComponent<TKey, TComponent> component);
    void RegsiterWith(TKey key, IComponent<TKey, TComponent> component);
}
Run Code Online (Sandbox Code Playgroud)

在你的情况下我是否可行,我不知道,但它肯定会避免类型问题.

另一个选择是投射this建议的消费者.这可能在执行时失败,但实际上除非你确实创建了一个替代实现,否则它不会.这有点烦人,在使用泛型时必须进行投射,但偶尔会发生.

编辑:这是一个如何出错的例子:

public class Other : IComponent<string, Other>
{
    // Implement interface
}
Run Code Online (Sandbox Code Playgroud)

现在如果你创建一个会发生什么Component<string, Other>?它满足约束没有问题......但是a Component不是Other......

现在您可以像这样更改约束:

public class Component<TKey, TComponent> : IComponent<TKey, TComponent> 
    where TComponent : Component<TKey, TComponent>
Run Code Online (Sandbox Code Playgroud)

即限制TComponentComponent,而不是IComponent.但仍有问题:

public class FooComponent : Component<string, FooComponent> {}
public class BarComponent : Component<string, FooComponent> {}
Run Code Online (Sandbox Code Playgroud)

在这里,你可能想要BarComponent拥有TComponent它自己,但它有一个不同的组件.你到目前为止所显示的代码可能还可以,但这种怪癖可能会妨碍其他目标.值得考虑...

哦,如果你很高兴Component密封,那么改变的约束足够了(我想!).