2013-08-28 55 views
2

我被困在使用.NET 3.5的項目中,我正在努力。我遇到了一個小問題,但惱人的協變問題。這是一個類似的模式,以我目前有:接口的協方差問題導致來回鑄造

public interface ISupportSomething<T> where T : struct 
{ 
    T StructProperty { get; set; } 
} 

public class SupportSomething : ISupportSomething<int> 
{ 
    public int StructProperty { get; set; } 
} 

public static class ISupportSomethingExtensions 
{ 
    public static IEnumerable<ISupportSomething<T>> Method<T> 
      (this IEnumerable<ISupportSomething<T>> collection) 
    { 
     return null; 
    } 
} 

public class SupportTester 
{ 
    private void SomeMethod() 
    { 
     IEnumerable<SupportSomething> source; 

     // invalid, i would generally fix this with a covariant 
     // declaration: ISupportSomething<out T> 
     var methodResult1 = source.Method(); 

     // valid 
     var methodResult2 = source.Cast<ISupportSomething<int>>().Method(); 

     // this means that if i want to make a function that 
     // returns an IEnumerable<SupportSomething> that 
     // has called ISupportSomethingExtensions.Method i 
     // have to do this cast back and forth approach 

    } 

    // here is a similar function to what i have that showcases the ugliness 
    // of calling this extension method 
    private IEnumerable<SupportSomething> SomeFunction() 
    { 
     IEnumerable<SupportSomething> source; 

     var tempSourceList = source.Cast<ISupportSomething<int>>(); 

     tempSourceList = tempSourceList.Method(); 

     return tempSourceList; // invalid 
     return tempSourceList.Cast<SupportSomething>(); //valid 
    } 
} 

我的問題很簡單,我想我已經知道答案,但:有沒有辦法,使用.NET 3.5,不就得這樣回並在處理這些對象時進行轉換(請參見上一個函數)?

我猜測我運氣不好,必須這樣做,因爲在.NET 4.0之前沒有對協方差的通用支持。

回答

0

您可以修改擴展方法,像這樣:

public static class ISupportSomethingExtensions 
{ 
    public static IEnumerable<T1> Method<T1, T2> 
      (this IEnumerable<T1> collection) 
     where T1 : ISupportSomething<T2> 
     where T2 : struct 
    { 
     return null; 
    } 
} 

現在並不需要依靠IEnumerable是協工作。

這種改變的不幸現場效果是Method將不再能夠有它的推斷通用的參數,你需要列出明確:

private IEnumerable<SupportSomething> SomeFunction() 
{ 
    IEnumerable<SupportSomething> source = Enumerable.Empty<SupportSomething>(); 

    return source.Method<SupportSomething, int>(); 
}