2012-02-29 59 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

你想在這裏完成什麼? – 2012-02-29 18:19:58

+0

你爲什麼想這樣做? – jrummell 2012-02-29 18:20:10

+0

它看起來像循環依賴於我... – user1096188 2012-02-29 18:20:50

回答

5

由於FAS按照我的理解,這是不可能的,這就是爲什麼:

你想,用B型 的模板的值要B,與A型

模板值

如果您創建了A的新實例,編譯器必須檢查T是否爲B.要檢查它是否爲B型,則必須檢查B是否爲A型,A型是B型等等。

您最終創建了一個無限循環。

+0

事實證明,這是可能的。我發佈瞭解決方案,因爲這個問題是第一個在Google上顯示的問題。聲明不能遞歸是正確的。你需要派生類才能工作。 – sbsmith 2017-11-02 16:08:25

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

因爲每個約束都是一個自引用類,而不是回引用類,所以沒有很好地解決問題。 – 2012-02-29 18:52:27

0

聽起來像是一個很好的問題給我。泛型的要點是它允許你抽象一個類以允許它使用多種類型。如果約束將類型限制爲具體類型,則只允許類型及其子類。如果您沒有爲子類執行此操作,請不要使用泛型。如果你是,使用界面怎麼樣?

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派生。 – 2012-02-29 19:06:14

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抽象化。