代码之家  ›  专栏  ›  技术社区  ›  Stefano Balzarotti

等价Java泛型循环引用C#

  •  4
  • Stefano Balzarotti  · 技术社区  · 7 年前

    我正在用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());
            }
    

    1 回复  |  直到 7 年前
        1
  •  4
  •   Ondrej Tucny    7 年前

    你看到的不是循环引用。类型参数约束只允许传入一个类型,该类型是该约束指定的泛型类型的后代。

    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> { }