2012-02-29 7 views
1

Я хочу, чтобы два родовых класса могли ссылаться друг на друга. Кажется, я ничего не могу скомпилировать. Пробовал это:C# перекрестные ссылки общие классы

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

Это практическая реализация, но я хотел избежать сложного объяснения своего собственного кода. Я могу создавать закрытые классы, которые подчиняются правилу, я просто не могу описать общий класс или интерфейс для этих закрытых экземпляров.

+2

Что вы пытаетесь достичь здесь? –

+0

Почему вы хотите это сделать? – jrummell

+0

Похоже на циклическую зависимость от меня ... – user1096188

ответ

5

Как фас, как я понимаю, что это невозможно, и вот почему:

Вы хотите, со значением шаблона типа B. Вы хотите B, со значением матричного типа А.

Если вы создаете новый экземпляр A, компилятор должен проверить, что T имеет тип B. Чтобы проверить, является ли он типом B, он должен проверить, является ли B типа A, A типа B и т. Д.

Вы создаете бесконечный цикл.

+0

Оказывается, это возможно. Я опубликовал решение, так как этот вопрос является одним из первых, который появляется в Google. Правильно, что декларация не может быть рекурсивной. Вы должны получить класс для его работы. – sbsmith

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

Отсутствует проблема, которая не отвечает на проблему, потому что каждое ограничение относится к классу саморекламы, а не к ссылочному классу. –

0

звучит как хороший вопрос для меня. Точка Generics это позволяет вам абстрагировать класс, чтобы позволить ему использовать несколько типов. Если ограничение ограничивает тип конкретным типом, вы разрешаете только тип и его подклассы. Если вы не делаете этого для подклассов, не используйте дженерики. Если да, то как насчет использования интерфейса?

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

Кажется, что они не могут быть получены из ClassA. –

0

То, как я закончил это, было добавление класса как одного из его собственных параметров типа. Это не слишком красиво, но оно работает.

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

Это возможно, на основе ответа на вопрос 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.

Смежные вопросы