C#交叉引用泛型类

时间:2012-02-29 18:16:21

标签: c# generics

我希望两个泛型类能够互相引用。我似乎无法编译任何东西。试过这个:

class Program
{
    static void Main(string[] args)
    {
    }

    public class ClassA<BT> where BT: ClassB<ClassA<BT>>
    {
        BT btvar;
    }

    public class ClassB<AT> where AT: ClassA<ClassB<AT>>
    {
        AT atvar;
    }
}

这有一个实际的实现,但我想避免对我自己的代码进行复杂的解释。我可以创建遵循规则的封闭类,我似乎无法描述那些封闭实例的泛型类或接口。

5 个答案:

答案 0 :(得分:5)

据我所知,这是不可能的,这就是原因:

你想要A,模板值为B型。 你想要B,模板值是A型。

如果你创建一个新的A实例,编译器必须检查T是否为B类。要检查它是否是B类,它必须检查B是A类型,A类型B等等。

你最终会创造一个无限循环。

答案 1 :(得分:1)

我最终这样做的方法是将类添加为自己的类型参数之一。它不太漂亮,但它有效。

public abstract class Saver<TSaver, TData>
    where TSaver : Saver<TSaver, TData>
    where TData : ISaveable<TData, TSaver>
{ ... }

public interface ISaveable<TData, TSaver>
    where TData : ISaveable<TData, TSaver>
    where TSaver : Saver<TSaver, TData>
{ ... }

public class WorkspaceWindow : ScalingWindow, ISaveable<WorkspaceWindow, WorkspaceWindowSaver>
{ ... }

public class WorkspaceWindowSaver : Saver<WorkspaceWindowSaver, WorkspaceWindow>
{ ... }

答案 2 :(得分:1)

这是可能的,以下是基于this question的答案。

public class ClassA<BT, AT> :
    where BT : ClassB<AT, BT>
    where AT : ClassA<BT, AT>
{
    BT btvar;
}

public class ClassB<AT, BT> :
    where BT : ClassB<AT, BT>
    where AT : ClassA<BT, AT>   
{
    AT atvar;
}

您将无法直接使用这些类,您需要覆盖它们。

public ClassAImp : ClassA<ClassBImp, ClassAImp>
public ClassBImp : ClassB<ClassAImp, ClassBImp>

所以你也可以制作ClassA和ClassB摘要。

答案 3 :(得分:0)

这将编译,但我想看到你实例化ClassA或ClassB:

    public class ClassA<TBt>  where TBt : ClassB<TBt>
    {
        TBt _btvar;
    }

    public class ClassB<TAt> : ClassA<TAt> where TAt : ClassB<TAt>
    {
        TAt _atvar;
    }

答案 4 :(得分:0)

&#34;你为什么要这样做?&#34;听起来对我来说是个好问题。泛型的重点是它允许你抽象一个类以允许它使用多种类型。如果约束将类型限制为具体类型,则只允许类型及其子类。如果你没有为子类做这个,不要使用泛型。如果是的话,使用界面怎么样?

public interface IClassA<ITB> { }

public interface IClassB<ITA> { }

public class ClassA<AT,BT> : IClassA<BT> where BT : IClassB<AT>
{
    BT btvar;
}

public class ClassB<BT,AT> : IClassB<AT> where AT : IClassA<BT>
{
    AT atvar;
}

public class ClassADerivedClosed : ClassA<ClassADerivedClosed, ClassBDerivedClosed> { }

public class ClassBDerivedClosed : ClassB<ClassBDerivedClosed, ClassADerivedClosed> { }