2012-01-26 150 views
2

這應該可以使用C#4和VS 2010嗎?我正在對實現通用接口的類進行一些處理,並且在處理之後想要將對象轉換爲更簡單的接口,以便我可以提取由通用接口定義的某些屬性。C#通用接口鑄造問題

interface IMyInterface 
{ 
    public Id { get; set; } 
} 

interface IFile<T1, T2> where T1 : IMyInterface where T2 : IMyInterface 
{ 
    Int64 prop1 { get; set; } 
    T1 t1 { get; set; } 
    T2 t2 { get; set; } 
} 

ClassA : IMyInterface 
{ 
    ... Implement some properties plus interface 
    public Id { get; set; } 
} 

ClassB : IMyInterface 
{ 
    ... Implement some properties plus interface 
    public Id { get; set; } 
} 

例如,這類有ClassX和優雅的,我想是某些類型的用於處理/保存,但是在那之後我只要提取等的ID,其是常見的實現此通用的所有類之間的共同屬性接口(其他屬性是不常見的在T1,T1)

ClassSomething : IFile<ClassA, ClassB> 
{ 
    ... Implement properties plus interface 
    public ClassX t1 
    { get {} set {} } 
    public ClassY t2 
    { get {} set {} } 
} 



IList<IFile<TItem1, TItem2>> list = new List<IFile<TItem1, TItem2>>() 
    ClassA ca = new ClassA(); 
    ... Fill in the interface defined properties 
    ... Fill the list with objects of ClassSomething 

foreach (IFile<TItem1, TItem2> x in list) 
{ 
    // This fails 
    IFile<IMyInterface, IMyInterface> interfaceItem = 
     (IFile<IMyInterface, IMyInterface>)x; 
} 

x上述(t1t2性質特異性)的流延到簡單IMyInterface接口出現故障。

有很多通用接口問題,但我沒有看到(或認識到)任何解決方案。

+1

你可能需要看看c#4.0的協方差和反變化 – ca9163d9

+0

哇,快速和好看的答案。我需要採取一些並消化答案。 :) – lko

+0

偉大的答案,他們都是有益的,我會選擇一個基於普遍投票的答案。 (我<3 SO) – lko

回答

5

您正在查找的解決方案稱爲variance(協方差和反變量)。但是你IMyInterface不能進行或者在T1T2協變或逆變,因爲它具有公共getter和公共setter方法接受T1T2

interface IAnimal {} 
class Dog : IAnimal { public void Bark() ; } 
class Cat : IAnimal { public void Meow() ; } 

var dogs = new FileImpl<Dog, Dog>() ; 
dogs.t1 = new Dog() ; 

var file = (IFile<IAnimal, IAnimal>) dogs ; // if this were OK... 
file.t1 = new Cat() ;      // this would have to work 
dogs.t1.Bark() ;       // oops, t1 is a cat now 
1

爲什麼只是不訪問x.T1x.T2,然後投給IMyInterface

foreach (IFile<TItem1, TItem2> x in list) 
{ 
    var t1 = x.T1 as IMyInterface; 
    var t2 = x.T2 as IMyInterface; 
} 
1

我認爲你會將泛型約束與繼承混爲一談。一個與另一個無關。通用接口上的約束是編譯器指令,它告訴編譯器泛型參數必須滿足特定的要求。從邏輯上說,對我們來說,這意味着ClassSomething肯定有IMyInterface的執行。但這就是我們,編譯器不會將這些約束轉換爲任何類型的繼承映射,所以它仍然只知道它是實現IFile<ClassA, ClassB>ClassSomething的實例。所以它不會讓你直接把它轉換成IFile<IMyInterface, IMyInterface>

2

只是對安東Tykhyy的答案擴大,

是,如果您願意/能夠對您的IFile接口進行以下更改,則可以使用C#4實現此目的:

interface IFile<out T1, out T2> where T1 : IMyInterface where T2 : IMyInterface 
{ 
    Int64 prop1 { get; set; } 
    T1 t1 { get; } 
    T2 t2 { get; } 
} 

我已將out關鍵字添加到泛型參數中,並且我已經從t1和t2屬性中刪除了。

+1

同意你,如果可能的話,我也會應用協變。 –