2014-08-27 58 views
0

如果有以下克拉森具有相同的接口選擇一個集合

public interface ISomething { int Id { get; set; } } 
public class SomethingA : ISomething {...} 
public class SomethingB : ISomething {...} 

在另一類我有以下兩個列表:

List<SomethingA> aValues; 
List<SomethingB> bValues; 

我的問題是,如果有可能做這樣的事情:

public List<ISomething> GetList(bool select) { 
    return select ? aValues : bValues; 
} 

我的目標就是用這個,因爲這:

GetList(true).Single(x => x.Id) // or 
foreach (var value in GetList(false)) 
{ 
    value.Id = 18; 
} 
// anything else 

更新: 我看,有很好的可能性。但是,還有一種方法可以實現以下目標嗎?

GetList(true).Remove(myValue); 

回答

2

您不能返回List<ISomething>因爲List<T>不協變類不能。 IEnumerable<T>是協變的,你可以使用它作爲只讀序列。

更改方法返回IEnumerable<ISomething>

public static IEnumerable<ISomething> GetList(bool select) 
{ 
    return select ? (IEnumerable<ISomething>)aValues :bValues; 
} 

然後做

var result = GetList(true).Single(x => x.Id == 0); 
foreach (var value in GetList(false)) 
{ 
    value.Id = 18; 
} 

至於你的更新:如果你想刪除您需要減掉一些靈活性的項目。 I.e使用非通用IList作爲返回類型。

public static IList GetList(bool select) 
{ 
    return select ? (IList)aValues : bValues; 
} 

然後做

IList list = GetList(true); 
foreach (var value in list.OfType<ISomething>())//OfType or Cast can be used 
{ 
    if (value.Id == 6)//Whatever condition 
    { 
     list.Remove(value); 
     break; 
    } 
} 
+0

請注意downvote的一些解釋?我測試過,並且工作。 – 2014-08-27 14:21:20

+0

謝謝,我的+1。對於我的大多數情況來說,這似乎是最簡單的解決方案。 – Matt 2014-08-27 14:25:50

+0

爲什麼你不能返回列表? (並且我不是downvoter :)) – DaniCE 2014-08-27 14:26:22

-1

您可以使用.Cast<T>方法是這樣的:

if (select) 
{ 
    return aValues.Cast<ISomething>().ToList(); 
} 
else 
{ 
    return bValues.Cast<ISomething>().ToList(); 
} 

或添加的所有項目的commong麗絲()這樣的:

var ret = new List<ISomething>(); 
if (select) 
{ 
    ret.AddRange(aValues); 
} 
else 
{ 
    ret.AddRange(bValues); 
} 
return ret; 

既然你只想迭代它,我會寫這樣的方法:

public IEnumerable<ISomething> GetList(bool select) { 
    return select ? aValues.Cast<ISomething>() : bValues.Cast<ISomething>(); 
} 

您也可以看看這個StackOverflow question

0

最簡單的辦法可以使用LINQ演員()是這樣的:

public List<ISomething> GetList(bool select) 
    { 
     return (List<ISomething>)(@select ? aValues.Cast<ISomething>() : bValues.Cast<ISomething>()); 
    } 

我看到,有很好的機會。但是,還有一種方法可以實現以下目標嗎? GetList(true).Remove(myValue);

要從原始列表中刪除,您可能最擅長使用其他人建議的關於該類的專門的Remove方法,因爲此處的大多數解決方案會返回原始列表的副本。 您可以很容易地從列表的副本中移除元素,但我明白這不是您要求的。

var result = GetList(true); 
    result.Remove(myValue); 
+0

@Adriano根據你的澄清更新了我的迴應,因爲問題有些不清楚。 – wezzix 2014-08-27 18:33:38

0

我喜歡OfType延伸,因爲它返回類型列表中,您需要

var listA = initialList.OfType<TypeA>(); //return List<TypeA> 
var listB = initialList.OfType<TypeB>(); //return List<TypeB> 

所以你的情況你開始

var aValues = List<ISomething>.OfType<SomethingA>() 

,然後你可以遍歷在任何一個子集合你需要。當然,你正在使用IEnumerable,但可以隱式轉換回IEnumerable<ITest>

如果您想篩選出價值,我會創造明確的方法將其刪除,但它取決於你所需要的在年底前實現(例如在ID而不是整個對象比較):

public IEnumerable<T> Remove<T>(this List<IDisposable> values, T valueToRemove) where T: IComparable 
{ 
    return values.OfType<T>().Where(t => valueToRemove.CompareTo(t) != 0); 
} 
相關問題