由特定通用包含接口参数化的通用容器接口

时间:2014-07-02 19:51:09

标签: c# generics interface containers restriction

目标:

创建通过实现另一个特定通用接口的类型参数化的通用接口。

问题:

我正在尝试在C#中编写以下相关接口,但我无法确定我尝试做的是否可行。

public interface IVersion<T>
{
    IVersionManager<IVersion<T>> Parent { get; }
    // various other methods
}

public interface IVersionManager<T> where T : IVersion<T>
{
    IReadOnlyList<T> Versions { get; }
    T Current { get; }
    void AddVersion(T version);
    // various other methods
}

不幸的是,Visual Studio似乎在IVersionManager<IVersion<T>>界面中找到了自引用(IVersion<T>)而非冒犯。

它会抛出以下错误:

  

IVersion<T>”类型必须可转换为“IVersion<IVersion<T>>”   以便在通用接口中将其用作参数“T”   'IVersionManager<T>'

这听起来好像它是循环的,但我认为它不是。

对我来说很有意义。我疯了吗?这可能吗?我只是希望子版本能够引用它的父管理器。

谷歌搜索没有发现任何事情。我怀疑也许我只是不知道如何说出这个问题。

4 个答案:

答案 0 :(得分:4)

我认为它应该是:

public interface IVersion<T>
{
    IVersionManager<T> Parent { get; }
    // various other methods
}

public interface IVersionManager<T>
{
    IReadOnlyList<IVersion<T>> Versions { get; }
    IVersion<T> Current { get; }
    void AddVersion(IVersion<T> version);
    // various other methods
}

无需定义where约束来实现类型安全。但缺点是您的VersionManagers不是由实际的Version<T>类型定义,而是由用于定义T的{​​{1}}类型定义。


我不知道是否有任何真正的方法可以同时使用一个通用参数来定义Version<T>泛型参数和IVersion's IVersionManager上的IVersion泛型。

因此,要在IVersion实施者上实现真正的“通用性”,您必须使用更复杂的类型和限制:

public interface IVersion<T>
{
    IVersionManager<T> Parent { get; }
    // various other methods
}

public interface IVersionManager<TVersion, T> 
    where TVersion : IVersion<T>
{
    IReadOnlyList<TVersion> Versions { get; }
    TVersion Current { get; }
    void AddVersion(TVersion version);
    // various other methods
}

这有点多余和笨拙,但允许创建更多指定的VersionManagers,这些IVersion实施者是真正通用的。{/ p>

答案 1 :(得分:1)

如果您想避免在IVersion上设置约束,可以在IVersionManager上扩展约束。但是,它有点笨拙,因为你必须传递两次T2的类型

public interface IVersion<T>
{
    IVersionManager<IVersion<T>, T> Parent { get; }
}

public interface IVersionManager<T, T2> where T : IVersion<T2>
{
    IReadOnlyList<T2> Versions { get; }
    T2 Current { get; }
    void AddVersion(T2 version);
    // various other methods
}

答案 2 :(得分:0)

您可以通过向Version<T>添加限制来编译

// Define other methods and classes here
public interface IVersion<T> where T:IVersion<T>   // <----- add restriction here
{
    IVersionManager<T> Parent { get; }  // <--- change generic type here
    // various other methods
}

public interface IVersionManager<T> where T : IVersion<T>
{
    IReadOnlyList<T> Versions { get; }  
    T Current { get; }
    void AddVersion(T version);
    // various other methods
}

是否正确是否取决于您确定......

答案 3 :(得分:0)

您需要在T中向IVersion添加约束:

public interface IVersion<T> where T : IVersion<T>
{
    IVersionManager<T> Parent { get; }
    // various other methods
}