2013-04-04 39 views
3

實施兩次相同的通用接口,具有類型參數的約束

public interface IGeneric<T>{} 

public class Student{} 

public class Teacher{} 

這是可能的

public class ConcreateClass : IGeneric<Student>, IGeneric<Teacher>{} 

這是不可能的

public class GenericClass<T1, T2> : IGeneric<T1>, IGeneric<T2> {} 

因爲GenericClass<String, String> instance;會引起歧義的兩個接口的實現。但爲什麼這是不可能的

public class GenericClassWithTypeConstraints<T1, T2> : IGeneric<T1>, IGeneric<T2> 
    where T1 : Student 
    where T2 : Teacher 
{} 

由於T1和T2不能是同一類? (編譯器誤差是相同的情況下,而不類型約束)

編輯
「Soner格尼爾」在Why does this result in CS0695提出了workarround,使用類繼承的兩個級別,這樣的:

public interface IGeneric<T> { String Name { get; } } 

public class Student{} 

public class Teacher{} 

public class GenericClassBase<T1> : IGeneric<T1> 
    where T1 : Student 
{ String IGeneric<T1>.Name { get { return "Generic class of Student"; } } } 

public class GenericClassDerived<T1, T2> : GenericClassBase<T1>, IGeneric<T2> 
    where T1 : Student 
    where T2 : Teacher 
{ String IGeneric<T2>.Name { get { return "Generic class of Teacher"; } } } 

這樣的代碼然後產生預期的結果

GenericClassDerived<Student, Teacher> X = new GenericClassDerived<Student, Teacher>(); 
Console.WriteLine(((IGeneric<Student>)X).Name); //outputs "Generic class of Student" 
Console.WriteLine(((IGeneric<Teacher>)X).Name); //outputs "Generic class of Teacher" 
+1

參見:[?爲何C#編譯器抱怨「類型可以結合」,當它們從不同的基類派生](http://stackoverflow.com/questions/7664790/why-does-the -c-sharp-compiler-complain-that-types-may-unify-when-they-derive-f),它非常相似。 – Ani 2013-04-04 07:30:15

+1

通過搜索CS0695找到[此問題](http://stackoverflow.com/questions/15316898/why-does-this-result-in-cs0695)。答案包括規範參考,包括:「在確定所有可能的構造類型時,不考慮約束聲明。」 – 2013-04-04 07:34:35

+0

@Ani謝謝,現在我明白,這是不可能的定義的C#。這可能也是VB的情況。 – Karuzo 2013-04-04 08:19:29

回答

1

爲T1和T2不能成爲同一班?

是的,他們可以是同一個班級。約束不能是sealed類因此Teacher可以從Student導出,反之亦然。這不合邏輯,但編譯器不知道它。

例如,

using System; 

public class Student{} 

public class Teacher : Student{} 

public class GenericClassWithTypeConstraints<T1, T2> 
    where T1 : Student 
    where T2 : Teacher 
{} 

class Test { 
    static void Main() { 
     var obj = new GenericClassWithTypeConstraints<Teacher, Teacher>(); 
    } 
} 

將編譯沒有任何問題。 Demo


  1. Docs

    約束也可以是類的類型,諸如抽象基類。 但是,約束不能是值類型或密封類。

+0

謝謝你的回答。我的觀點是「學生」和「老師」不會互相繼承。但正如其他人回答的那樣,這並不重要,因爲不考慮類型限制。 – Karuzo 2013-04-04 08:34:19

+1

約束不能被密封的類是合乎邏輯的。密封修飾符可防止其他類從其繼承。 – 2013-04-04 08:38:25

相關問題