2013-07-01 43 views
2

我有下面的代碼生成擴展到IEnumerable<T>名單不繼承一個IEnumerable擴展方法

//http://stackoverflow.com/a/1779135/1180926 
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n) 
{ 
    //....... 
} 

當我嘗試將其應用到一個列表:

public static void RemoveTwo(List<string> strList) 
{ 
    strList = strList.SkipLast(2); 
} 

我得到以下錯誤:

Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'System.Collections.Generic.List'. An explicit conversion exists (are you missing a cast?)

但是List<T>繼承IEnumerable<T>src),所以不應該也繼承它的擴展方法嗎?

回答

5

你必須從IEnumerable<string>創建列表:

public static void RemoveTwo(List<string> strList) 
{ 
    strList = strList.SkipLast(2).ToList(); 
} 

你的擴展返回IEnumerable<string>這不是List<string>。但是,如果您要修改strList,則必須使用Lists(如Remove)修改原始集合的方法,或者必須返回新列表。

而不是SkipLast如果您要更改原始集合而不返回新列表,則應該使用RemoveAt

public static void RemoveTwo(List<string> strList) 
{ 
    if(strList.Count > 0) 
     strList.RemoveAt(strList.Count-1); 
    if(strList.Count > 0) 
     strList.RemoveAt(strList.Count-1); 
} 
+2

咄。感謝:-) – Arithmomaniac

2

您的問題不在於擴展方法(其工作方式是)的調用,但在其IEnumerable<string>返回值賦值給一個變量List<string>。爲了展示起見,下面的代碼將把 工作 編譯罰款(但什麼都不做):

public static void RemoveTwo(List<string> strList) 
{ 
    strList.SkipLast(2); 
} 
+0

編譯但對列表沒有任何意見,請查看關於newstackexinst的評論。回答 –

+0

@TimSchmelter:對,我應該說得更清楚。 – Douglas

2

你在做什麼錯被分配到列表中的IEnumerable<string>返回值。你不能這樣做,因爲即使所有的List<T>也是IEnumerable<T>,相反是不是真實。你需要做的是添加一個ToList()SkipLast通話結束:

public static List<string> RemoveTwo(List<string> strList) 
{ 
    return strList.SkipLast(2).ToList(); 
} 
+0

你又被New-Memberese絆倒了:)。你的代碼對原始列表沒有任何作用,爲了讓你的代碼工作,你需要通過'ref'傳遞strList。 –

+0

@ScottChamberlain我正在重新分配它... –

+0

是的,你正在將它重新分配給本地變量'strList',但是傳遞給'RemoveTwo'函數的列表不會被修改。您需要以'ref'形式傳遞列表,以便在重新分配原始列表或將返回生成的新列表作爲返回值時更新。 –