我正在用C#移植Java库,发现这个奇怪的类使用了泛型循环引用:
public static class UserAgentAnalyzerDirectBuilder<UAA extends UserAgentAnalyzerDirect, B extends UserAgentAnalyzerDirectBuilder<UAA, B>>
{
// Implementation
}
我不太了解循环引用的工作方式,但据我所知确实是可能的。
该代码可以轻松转换为C#:
public class UserAgentAnalyzerDirectBuilder<UAA, B> where UAA: UserAgentAnalyzerDirect where B: UserAgentAnalyzerDirectBuilder<UAA, B>
{
// Implementation
}
假设我的等效类正确,那么我需要实现实例化该奇怪类的方法。
在Java中,我有以下代码:
public static UserAgentAnalyzerDirectBuilder<? extends UserAgentAnalyzer, ? extends UserAgentAnalyzerDirectBuilder<?, ?>> newBuilder() {
return new UserAgentAnalyzerDirectBuilder<>(new UserAgentAnalyzer());
}
在C#中,我试图复制:
public static UserAgentAnalyzerDirectBuilder<UAA, UserAgentAnalyzerDirectBuilder<UAA, B>> newBuilder<UAA, B>()
where UAA: UserAgentAnalyzerDirect
where B: UserAgentAnalyzerDirectBuilder<UAA, B>
{
return new UserAgentAnalyzerDirectBuilder<UAA, UserAgentAnalyzerDirectBuilder<UAA, B>> (new UserAgentAnalyzer());
}
但是它不起作用。我想知道我做错了什么吗,或者在C#泛型中是否确实可以进行循环引用。
答案 0 :(得分:4)
您看到的不是循环引用。类型参数约束只允许您传入一个类型,该类型是约束所指定的通用类型的后代。
下面的代码示例将编译,我认为它将满足您的需求:
public class UserAgentAnalyzerDirect { }
public class UserAgentAnalyzerDirectBuilder<UAA, B>
where UAA : UserAgentAnalyzerDirect
where B : UserAgentAnalyzerDirectBuilder<UAA, B>
{
// this method is supposed to implement the effect of the
// constructor in the original Java code
public void SetUAA(UAA a) { }
// further implementation
}
public static UserAgentAnalyzerDirectBuilder<UAA, B> NewBuilder<UAA, B>()
where UAA : UserAgentAnalyzerDirect, new()
where B : UserAgentAnalyzerDirectBuilder<UAA, B>, new()
{
// Unlike in Java, C# allows instantiating generic type parameters only using
// a parameter-less constructor. Hence we use the SetUAA method here instead.
var a = new UAA();
var b = new B();
b.SetUAA(a);
return b;
}
然后,您可以像上面这样创建通用类的自定义后代:
public class CustomUserAgentAnalyzerDirect : UserAgentAnalyzerDirect { }
public class CustomUserAgentAnalyzerDirectBuilder : UserAgentAnalyzerDirectBuilder<CustomUserAgentAnalyzerDirect, CustomUserAgentAnalyzerDirectBuilder> { }