[英]C# Casting a List<ObjBase> as List<Obj>
為什么我不能將List<ObjBase>
為List<Obj>
? 為什么以下不起作用:
internal class ObjBase
{
}
internal class Obj : ObjBase
{
}
internal class ObjManager
{
internal List<Obj> returnStuff()
{
return getSomeStuff() as List<Obj>;
}
private List<ObjBase> getSomeStuff()
{
return new List<ObjBase>();
}
}
相反,我必須這樣做:
internal class ObjBase
{
}
internal class Obj : ObjBase
{
}
internal class ObjManager
{
internal List<Obj> returnStuff()
{
List<ObjBase> returnedList = getSomeStuff();
List<Obj> listToReturn = new List<Obj>(returnedList.Count);
foreach (ObjBase currentBaseObject in returnedList)
{
listToReturn.Add(currentBaseObject as Obj);
}
return listToReturn;
}
private List<ObjBase> getSomeStuff()
{
return new List<ObjBase>();
}
}
我在Visual Studio 2008中收到以下錯誤(為了便於閱讀而縮短):
無法通過引用轉換,裝箱轉換,取消裝箱轉換,換行轉換或空類型轉換將類型“列表”轉換為“列表”
謝謝。
您可以使用System.Linq中的Cast
和ToList
擴展方法將其放在一行中。
代替
internal List<Obj> returnStuff()
{
return getSomeStuff() as List<Obj>;
}
做這個:
internal List<Obj> returnStuff()
{
return getSomeStuff().Cast<Obj>().ToList();
}
我只能從Java視圖中描述“問題”,但是我知道這個方面在C#和Java中都是相同的:
List<ObjBase>
不是List<Obj>
,因為它可能包含一個不是Obj
對象的ObjBase
對象。
List<Obj>
的另一種方法不能轉換為List<ObjBase>
因為前者保證接受帶有ObjBase
參數的Add()
調用,后者不接受!
總結一下:即使Obj
是一個ObjBase
, List<Obj>
也不是List<ObjBase>
。
我認為你誤解了你想要做的演員。 您正在考慮更改列表中存儲的對象的類型,您實際上正在嘗試更改列表本身的類型。 更有意義的是,您無法更改列表本身,因為您已經填充了它。
您可以將其視為基類列表,然后在處理列表項時將其強制轉換,這將是我的方法。
這次嘗試演員的目的是什么?
C#目前不支持泛型類型的方差。 根據我的閱讀,這將在4.0中改變。
有關泛型差異的更多信息,請參見此處 。
list.ConvertAll看起來很誘人,但有一個很大的缺點:它將創建一個全新的列表。 這將影響性能和內存使用,尤其是對於大型列表。
通過更多努力,您可以創建一個包裝列表類,將原始列表保留為內部引用,並僅在使用它們時轉換項目。
用法:
var x = new List<ObjBase>();
var y = x.CastList<ObjBase, Obj>(); // y is now an IList<Obj>
要添加到庫中的代碼:
public static class Extensions
{
public static IList<TTo> CastList<TFrom, TTo>(this IList<TFrom> list)
{
return new CastedList<TTo, TFrom>(list);
}
}
public class CastedList<TTo, TFrom> : IList<TTo>
{
public IList<TFrom> BaseList;
public CastedList(IList<TFrom> baseList)
{
BaseList = baseList;
}
// IEnumerable
IEnumerator IEnumerable.GetEnumerator() { return BaseList.GetEnumerator(); }
// IEnumerable<>
public IEnumerator<TTo> GetEnumerator() { return new CastedEnumerator<TTo, TFrom>(BaseList.GetEnumerator()); }
// ICollection
public int Count { get { return BaseList.Count; } }
public bool IsReadOnly { get { return BaseList.IsReadOnly; } }
public void Add(TTo item) { BaseList.Add((TFrom)(object)item); }
public void Clear() { BaseList.Clear(); }
public bool Contains(TTo item) { return BaseList.Contains((TFrom)(object)item); }
public void CopyTo(TTo[] array, int arrayIndex) { BaseList.CopyTo((TFrom[])(object)array, arrayIndex); }
public bool Remove(TTo item) { return BaseList.Remove((TFrom)(object)item); }
// IList
public TTo this[int index]
{
get { return (TTo)(object)BaseList[index]; }
set { BaseList[index] = (TFrom)(object)value; }
}
public int IndexOf(TTo item) { return BaseList.IndexOf((TFrom)(object)item); }
public void Insert(int index, TTo item) { BaseList.Insert(index, (TFrom)(object)item); }
public void RemoveAt(int index) { BaseList.RemoveAt(index); }
}
public class CastedEnumerator<TTo, TFrom> : IEnumerator<TTo>
{
public IEnumerator<TFrom> BaseEnumerator;
public CastedEnumerator(IEnumerator<TFrom> baseEnumerator)
{
BaseEnumerator = baseEnumerator;
}
// IDisposable
public void Dispose() { BaseEnumerator.Dispose(); }
// IEnumerator
object IEnumerator.Current { get { return BaseEnumerator.Current; } }
public bool MoveNext() { return BaseEnumerator.MoveNext(); }
public void Reset() { BaseEnumerator.Reset(); }
// IEnumerator<>
public TTo Current { get { return (TTo)(object)BaseEnumerator.Current; } }
}
Linq有一個ConvertAll方法。 所以像
list.ConvertAll<Obj>(objBase => objbase.ConvertTo(obj));
我不確定還有什么建議。 我假設ObjBase是基類,如果所有ObjBase對象都是Obj對象,我不確定為什么你會首先擁有這兩個對象。 也許我不合時宜。
編輯:list.Cast方法比上面的方法更好,假設它們可以相互轉換。 在我閱讀其他答案之前忘了這一點。
這是C#的主要痛苦 - 這就是仿制葯的設計方式。 List不擴展List,它只是一個完全不同的類型。 您無法以任何方式將它們轉換或分配給對方,您唯一的選擇是將一個列表復制到另一個列表。
拉撒路 :
我認為編譯器會意識到我希望對列表的對象進行操作,而不是我試圖自己編譯列表。
更多信息:
public abstract class ObjBase
{
}
internal interface IDatabaseObject
{
}
public class Obj : ObjBase, IDatabaseObject
{
}
internal interface IDatabaseObjectManager
{
List<ObjBase> getSomeStuff();
}
public class ObjManager : IObjManager
{
public List<Obj> returnStuff()
{
return getSomeStuff().Cast <Customer>().ToList<Customer>();
}
private List<ObjBase> getSomeStuff()
{
return new List<ObjBase>();
}
}
現在這個DLL之外的客戶端代碼可以去:ObjManager objM = new ObjManager(); 列表listOB = objM.returnStuff(); 我將為應用程序的這個部分(O / RM)創建幾個Obj
和ObjManager
類型。
(Darn評論塊用完了字符!:-)
以下是我如何修復轉換
list<SomeOtherObject>
到了
object
然后到了
List<object>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.