我创建了一个基类("元素")和一个基类列表("元素")作为泛型类.通用列表类应该只能包含类,这些类是从"Element"派生的Type"Element"."Element"类应该拥有一个"ParentRoot"属性,该属性应该包含基类列表类("Elements")!
public class Element
{
public Elements<Element> ParentRoot { get; set; }
}
public class Elements<T> : List<T> where T : Element
{
}
Run Code Online (Sandbox Code Playgroud)
现在我创建两个类和两个列表类,它们是从上面的类派生的.但我没有设置"ParentRoot"属性:
public class Ceiling : Element
{
public Ceiling(Ceilings parent)
{
Parent = parent;
ParentRoot = parent;
}
public Ceilings Parent { get; set; }
}
public class Ceilings : Elements<Ceiling>
{
}
public class Wall : Element
{
public Wall(Walls parent)
{
Parent = parent;
ParentRoot = parent;
}
public Walls Parent { get; set; }
}
public class Walls : Elements<Wall>
{
}
Run Code Online (Sandbox Code Playgroud)
我得到两个错误:
ParentRoot = parent;
Run Code Online (Sandbox Code Playgroud)
无法将"Ceilings"类型隐式转换为"Elements",无法将类型"Walls"隐式转换为"Elements"
有这个问题的解决方案吗?
谢谢你的帮助!
编辑:
好的,我必须更具体一点.我稍微扩展了代码:
public class Room
{
public Room(Rooms parent)
{
Parent = parent;
}
public Rooms Parent { get; set; }
}
public class Rooms : List<Room>
{
}
public class Element
{
public Elements<Element> ParentRoot { get; set; }
public Rooms FindRoomsToElement()
{
Rooms rooms = new Rooms();
foreach (Room room in ParentRoot.Parent.Parent)
{
// Do stuff here
// if i rename the "ParentRoot" property to "Parent" and make it "virtual",
// and the other properties overwrite it with the "new" key, then this will
// get a null exception!
// i haven't testet it, but i think abstrakt will bring the same/similar result
// if i make the "ParentRoot" property IEnumerable, then there will no
// ParentRoot.Parent be available
}
return rooms;
}
}
public class Elements<T> : List<T> where T : Element
{
public Elements(Room parent)
{
Parent = parent;
}
public Room Parent { get; set; }
}
public class Ceiling : Element
{
public Ceiling(Ceilings parent)
{
Parent = parent;
//ParentRoot = parent;
}
public Ceilings Parent { get; set; }
}
public class Ceilings : Elements<Ceiling>
{
public Ceilings(Room parent) : base(parent)
{
}
}
public class Wall : Element
{
public Wall(Walls parent)
{
Parent = parent;
//ParentRoot = parent;
}
public Walls Parent { get; set; }
}
public class Walls : Elements<Wall>
{
public Walls(Room parent) : base(parent)
{
}
}
Run Code Online (Sandbox Code Playgroud)
我希望这会使它更精确.
你不能这样做,因为如果可以的话,你可以将错误的元素放入List.
Elements<Ceilings> ceilings = someCeilings;
Elements<Element> parentRoot = ceilings; // Not allowed; imagine it is though.
Wall wall = someWall;
parentRoot.Add(wall); // Oops - we just added a wall to someCeilings!
Run Code Online (Sandbox Code Playgroud)
如果您可以将墙和/或天花板视为一个序列,您可以IEnumerable<Element>改为使用(因为它IEnumerable<T>是"协变的"):
IEnumerable<Element> parentRoot = ceilings; // OK
Run Code Online (Sandbox Code Playgroud)
这没关系,因为IEnumerable<Element>无法修改原始集合.
问题是,给定 aGeneric<T>和 a Child : Base,该类型Generic<Base>不是 的基数Generic<Child>。泛型不是其具体实现的基类 -它们是可以创建具体实现的模板,反过来,具体实现彼此之间没有层次关系。请考虑以下代码片段以了解为什么会这样:
var bananas = List<Banana>();
var fruits = (List<Fruit>)bananas; // If this was valid
fruits.Add(new Orange()); // Then this would be valid
// So we'd have an Orange to a list of runtime type List<Banana>
Run Code Online (Sandbox Code Playgroud)
因此,你的Elements<Element>,即上述 I 的情况Generic<Base>,不能作为其他人的基础。您的Ceilings和Walls既不能隐式也不能显式转换为Elements<Element>.
一种可能的解决方法是创建ParentRoot一个虚拟的或更好的抽象属性(如果Element可以是抽象的) ,并在 的每个子类中重写它Element,以手动将属性转换Parent为Elements<Element>类型。
例如,您可以像这样更改您的基础和通用:
public abstract class Element
{
public abstract Elements<Element> ParentRoot { get; }
}
public class Elements<T> : List<T> where T : Element
{
public Elements<T>() : base()
{
}
public Elements<T>(ICollection<T> collection) : base(collection)
{
}
}
Run Code Online (Sandbox Code Playgroud)
然后,对于每个子类,执行以下操作:
public class Wall : Element
{
public Wall(Walls parent)
{
Parent = parent;
}
public Walls Parent { get; set; }
public override Elements<Element> ParentRoot
{
get
{
return new Elements<Element>(Parent);
}
}
}
Run Code Online (Sandbox Code Playgroud)
当然,对返回的对象的修改ParentRoot不会影响Parent. 但这在语义上是可以的,因为(正如我用香蕉和橙子描述的那样),您不想仅仅因为它在代码中的某个时刻看起来 像 an就意外地将 a 添加Ceiling到 a 中。WallsElements<Element>
| 归档时间: |
|
| 查看次数: |
715 次 |
| 最近记录: |