设计问题如下,实际问题包括2个模块。
abstract class Letter
{
private int _id;
protected Letter(int id) { _id = id; }
public abstract string Val { get; }
}
class LetterA : Letter
{
public LetterA(int id) : base(id) {}
public override string Val
{
get { return "A"; }
}
}
class WordWithALettersOnly
{
public IList<LetterA> ALetters { get; set; }
}
class LetterSmallA : LetterA
{
public LetterSmallA(int id) : base(id) {}
public override string Val
{
get { return "a"; }
}
}
class WordWithSmallALettersOnly : WordWithALettersOnly
{
private IList<LetterSmallA> _aLetters;
public new IList<LetterSmallA> ALetters
{
get { return _aLetters; }
set
{
_aLetters = value;
if(_aLetters != null)
base.ALetters = value.Cast<LetterA>().ToList(); // <-- reference lost
}
}
}
class Program
{
static void Main(string[] args)
{
var smallAWordOnly = new WordwithSmallALettersOnly();
smallAWordOnly.ALetters = new List<LetterSmallA>(){new LetterSmallA(1)};
Console.WriteLine("d : " + smallAWordOnly.ALetters.Count); // --> 1
Console.WriteLine("b : " + ((WordwithALettersOnly)smallAWordOnly).ALetters.Count); // --> 1
smallAWordOnly.ALetters.Add(new LetterSmallA(2)); --> 2
Console.WriteLine("d : " + smallAWordOnly.ALetters.Count);
Console.WriteLine("b : " + ((WordwithALettersOnly)smallAWordOnly).ALetters.Count); // -> 1
}
}
本质上派生的类在模块2中生成,并在外部装配模块1中处理,在/ c引用丢失。
是将模块2的派生类对象转换为模块1类对象的唯一方法
我希望我已经清楚地解释了这个问题,如果不是我道歉,我会非常感谢这方面的解决方案。
答案 0 :(得分:0)
如果我正确理解您的问题,您希望将IList<LetterSmallA>
视为IList<LetterA>
。这在C#中是不可能的,并且有很好的理由:IList<LetterA>
所说的可能之一就是“尝试向其添加任何LetterA
。 IList<LetterSmallA>
无法做到这一点,因此没有内置的方法来做你想做的事。
您可以做的是创建自己的IList<T>
实现,该实现包含另一个IList<T>
派生类型:
class BaseTypeList<TBase, TDerived> : IList<TBase>
where TBase : class
where TDerived : class, TBase
{
private readonly IList<TDerived> m_derivedList;
public BaseTypeList(IList<TDerived> derivedList)
{
m_derivedList = derivedList;
}
public IEnumerator<TBase> GetEnumerator()
{
return m_derivedList.Cast<TBase>().GetEnumerator();
}
public void Add(TBase item)
{
var derivedItem = item as TDerived;
if (derivedItem == null)
throw new ArgumentException();
m_derivedList.Add(derivedItem);
}
public void Clear()
{
m_derivedList.Clear();
}
// other members implemented in a similar fashion
}
(class
约束不是必需的,但可以使代码更简单。)
ALetters
的setter可能如下所示:
_aLetters = value;
if(_aLetters == null)
base.ALetters = null;
else
base.ALetters = new BaseTypeList<LetterA, LetterSmallA>(value);