目标:
创建通过实现另一个特定通用接口的类型参数化的通用接口。
问题:
我正在尝试在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>
'
这听起来好像它是循环的,但我认为它不是。
对我来说很有意义。我疯了吗?这可能吗?我只是希望子版本能够引用它的父管理器。
谷歌搜索没有发现任何事情。我怀疑也许我只是不知道如何说出这个问题。
答案 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
}