简体   繁体   English

C#交叉引用泛型类

[英]C# cross referencing generic classes

I want two generic classes to be able to reference each other. 我希望两个泛型类能够相互引用。 I can't seem to get anything to compile. 我似乎无法编译任何东西。 Tried this: 试过这个:

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

This has a practical implementation, but I wanted to avoid a complicated explanation of my own code. 这是一个实际的实现,但是我想避免对自己的代码进行复杂的解释。 I can create closed classes that obey the rule, I just can't seem to describe a generic class or interface for those closed instances. 我可以创建符合规则的封闭类,但似乎无法为这些封闭实例描述通用类或接口。

As fas as I understand, this is impossible, and this is why: 据我所知,这是不可能的,这就是为什么:

You want A, with a template value of type B. You want B, with a template value of type A. 您想要A,模板类型为B。您想要B,模板值为类型A。

If you create a new instance of A, the compiler has to check of T is of type B. To check if it's type B, it has to check if B is of type A, A of type B, etc etc. 如果创建A的新实例,则编译器必须检查T的类型是否为B。要检查它的类型是否为B,则必须检查B的类型是否为A,A的类型是否为B,等等。

You end up creating an endless loop. 您最终会创建一个无限循环。

The way I ended up doing it was by adding the class as one of its own type parameters. 我最终完成此操作的方法是将类添加为自己的类型参数之一。 It's not too pretty, but it works. 它不是很漂亮,但是可以。

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

This is possible, the following is based on the answer to 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;
}

You won't be able to use the classes directly, you'll need to override them. 您将无法直接使用这些类,需要覆盖它们。

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

So you may as well make ClassA and ClassB abstract. 因此,您也可以使ClassA和ClassB抽象。

this will compile, but I would like to see you instantiate either ClassA or ClassB: 这将进行编译,但是我希望您实例化ClassA或ClassB:

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

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

"Why would you want to?" “你为什么要?” sounds like a good question to me. 听起来对我来说是个好问题。 The point of Generics it to allow you to abstract a class to allow it to use multiple types. 泛型的要点是允许您抽象一个类以允许它使用多种类型。 If the constraint limits the type to a concrete type, you are only allowing the type and its subclasses. 如果约束将类型限制为具体类型,则仅允许该类型及其子类。 If you aren't doing this for subclasses, don't use generics. 如果您不对子类执行此操作,请不要使用泛型。 If you are, how about using an interface? 如果是的话,如何使用界面?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM