為簡潔起見,我簡化了代碼。
有兩個基類Document和Line兩個派生自這些基類的類DocumentPlus和LinePlus。
Document并分別DocumentPlus包含一個List<Line>和List<LinePlus>。
public class Test
{
public class Document
{
public List<Line> Lines = new List<Line>();
}
public class Line
{
public string? A;
}
public class DocumentPlus : Document
{
public new List<LinePlus> Lines = new List<LinePlus>();
}
public class LinePlus : Line
{
public string? B;
}
public Test()
{
var x = new DocumentPlus();
x.Lines = new List<LinePlus>()
{
new LinePlus() { A = "123", B = "456" },
new LinePlus() { A = "789", B = "101" },
new LinePlus() { A = "112", B = "131" }
};
var y = (Document)x;
var z = y.Lines;
// Z should be the Lines entered above but as their base type
// Just not sure how to do it!
}
}
有什么辦法可以在將實體投射List<LinePlus>到List<Line>時投射到?DocumentPlusDocument
謝謝!
uj5u.com熱心網友回復:
將 DocumentPlus 實體轉換為 Document 時,有什么方法可以將 LinePlus 串列轉換為 Line 嗎?
不,因為List<LinePlus>屬于DocumentPlus而不是Document。
DocumentPlus宣告時使用new關鍵字Lines。這表明您要使用方法隱藏而不是覆寫;Document.Lines仍然是型別List<Line>,并且不參考與 . 相同的實體DocumentPlus.Lines。
事實上,他們不能參考同一個實體,因為List<LinePlus>與 無關List<Line>,考慮到List<T>一般是不變的。
如果您只是想轉換 DocumentPlus.Lines為 a List<Line>,那么這是完全可能的:
var z = x.Lines.ConvertAll(linePlus => (Line)linePlus);
但似乎您預期的繼承層次結構被破壞了。
uj5u.com熱心網友回復:
嘗試這個。
using System.Linq
public Document CastDocPlusToDoc(DocumentPlus inputDocP) {
Document outputDoc = new Document();
outputDoc.Lines.AddRange(inputDocP.LinesPlus.Cast<Lines>());
}
var y = CastDocPlusToDoc(x)
我什至不確定 .Cast 在這里是否必要
uj5u.com熱心網友回復:
解決這個問題的(可能的)“正確”方法是使用泛型 - 然后不需要強制轉換。Line列舉集合時,您只需獲得正確的型別。
public class Document<TLine> where TLine : Line
{
public List<TLine> Lines = new List<TLine>();
}
public class Line
{
public string? A;
}
public class DocumentPlus : Document<LinePlus>
{
}
public class LinePlus : Line
{
public string? B;
}
現場示例:https ://dotnetfiddle.net/BbfOAN
正如評論的那樣,這可能更適合您的要求
public class DocumentBase<TLine> where TLine : Line
{
public List<TLine> Lines = new List<TLine>();
}
public class Line
{
public string? A;
}
public class Document : DocumentBase<Line>
{
}
public class DocumentPlus : DocumentBase<LinePlus>
{
}
public class LinePlus : Line
{
public string? B;
}
LinePlus這種方法為您提供型別安全,因此在處理DocumentPlus實體時不需要您強制轉換。
uj5u.com熱心網友回復:
我已經使用這篇文章的答案實作了所需的功能:Convert List<DerivedClass> to List<BaseClass> - Answer by Bigjim
此解決方案使用一個包裝器,該包裝器CastedList<TTo, TFrom>實作IList<TTo>介面方法將專案從一種泛型型別轉換為另一種的方式。
public class CastedList<TTo, TFrom> : IList<TTo> where TTo : class where TFrom : class
{
public IList<TFrom> Items;
public CastedList(IList<TFrom> items)
{
Items = items;
}
// IEnumerable
IEnumerator IEnumerable.GetEnumerator() => Items.GetEnumerator();
// IEnumerable<T>
IEnumerator<TTo> IEnumerable<TTo>.GetEnumerator()
{
return new CastedEnumerator<TTo, TFrom>(Items.GetEnumerator());
}
// ICollection
public int Count => Items.Count;
public bool IsReadOnly => Items.IsReadOnly;
public void Add(TTo item)
{
if (item is TFrom castItem)
Items.Add(castItem);
}
public void Clear() => Items.Clear();
public bool Contains(TTo item)
{
if (item is TFrom castItem)
Items.Contains(castItem);
return false;
}
public void CopyTo(TTo[] array, int arrayIndex)
{
if (Items is TFrom[] castArray)
Items.CopyTo(castArray, arrayIndex);
}
public bool Remove(TTo item)
{
if (item is TFrom castItem)
Items.Remove(castItem);
return false;
}
// IList
public TTo this[int index]
{
get => (Items[index] as TTo)!;
set => Items[index] = (value as TFrom)!;
}
public int IndexOf(TTo item)
{
if (item is TFrom castItem)
Items.IndexOf(castItem);
return -1;
}
public void Insert(int index, TTo item)
{
if (item is TFrom castItem)
Items.Insert(index, castItem);
}
public void RemoveAt(int index) => Items.RemoveAt(index);
}
public class CastedEnumerator<TTo, TFrom> : IEnumerator<TTo> where TTo : class where TFrom : class
{
public IEnumerator<TFrom> BaseEnumerator;
public CastedEnumerator(IEnumerator<TFrom> baseEnumerator)
{
BaseEnumerator = baseEnumerator;
}
// IDisposable
public void Dispose() => BaseEnumerator.Dispose();
// IEnumerator
object IEnumerator.Current => BaseEnumerator.Current;
public bool MoveNext() => BaseEnumerator.MoveNext();
public void Reset() => BaseEnumerator.Reset();
// IEnumerator<TTo>
public TTo Current => (BaseEnumerator.Current as TTo)!;
}
public static class ListExtensions
{
public static IList<TTo> CastList<TTo, TFrom>(this IList<TFrom> list) where TTo : class, TFrom where TFrom : class
{
return new CastedList<TTo, TFrom>(list);
}
}
public class Test
{
public class Document
{
public IList<Line> Lines = new List<Line>();
}
public class Line
{
public string? A;
}
public class DocumentPlus : Document
{
public new IList<LinePlus> Lines
{
get => base.Lines.CastList<LinePlus, Line>();
set => base.Lines = value.Cast<Line>().ToList();
}
}
public class LinePlus : Line
{
public string? B;
}
public Test()
{
var DocumentP = new DocumentPlus();
DocumentP.Lines = new List<LinePlus>()
{
new LinePlus() { A = "123", B = "456" },
new LinePlus() { A = "123", B = "456" },
new LinePlus() { A = "123", B = "456" }
};
var x = DocumentP.Lines;
DocumentP.Lines.Add(new LinePlus());
var Document = (Document)DocumentP;
Document.Lines.Add(new LinePlus() { A = "789", B = "789" });
Document.Lines.Add(new Line() { A = "456" });
Document.Lines.Add(new Line() { A = "262" });
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/515857.html
標籤:C#遗产铸件
上一篇:如何在C 中為抽象類定義迭代器
