我有一个名为IHierarchable的接口,用于“Entity”类和“Scene”类,后者作为所有实体的根。
/// <summary>
/// Signifies that an object can exist in the game hierarchy and can have children.
/// </summary>
public interface IHierarchable
{
public abstract Scene Scene { get; protected init; }
/// <summary>
/// The parent of this object.
/// </summary>
public abstract IHierarchable Parent { get; protected set; }
/// <summary>
/// Any children belongong to this object.
/// </summary>
public abstract ReadOnlyCollection<IHierarchable> Children { get; protected set; }
}
但是当我在Scene类上实现这个时:
/// <summary>
/// A base 2D world, into which <see cref="Entity"/> instances can be placed.
/// </summary>
public class Scene : IHierarchable
{
Scene IHierarchable.Scene { get; init; }
public IHierarchable Parent { get; set; }
public ReadOnlyCollection<IHierarchable> Children { get; set; }
public Scene()
{
(this as IHierarchable).Scene = null;
}
}
我在构造函数中有以下错误:
仅初始化属性或索引器“IHierarchable”。只能在对象初始值设定项中,或在示例构造函数或init访问器中的this或base上分配Scene
我必须在这个类中显式地实现接口,因为'Scene'属性碰巧共享'Scene'类的名称。但是,一旦我以这种方式实现它,我就无法实际设置该属性,即使我在Scene的构造函数中设置它并使用'this'关键字,就像错误消息所建议的那样。
2条答案
按热度按时间oxiaedzo1#
您定义的
interface
类型using DIM syntax不是您想要的。我很理解这是造成混乱的一个重要原因,特别是它也是一个非常新的语言特性。DIM属性的一个大问题是,
interface
类型(包括DIM接口)不能有字段,因此不能有自动属性,因此当在DIM接口中使用C#class
/struct
自动属性语法时,实际上只是定义了一个类似abstract
的属性interface
类型更改为 good old ' fashionedinterface
:Scene
和Parent
设置为可空属性,因为我假设最上面的IHierarchable
对象最终会有一个null
父对象,并且您显式地设置了Scene = null
,所以我假设这是故意的。null
ordefault
-这是CLR中隐含的。IHierarchable
旨在成为其消费者的只读接口(即。例如,IHierarchable
的消费者不应该能够覆盖任何属性-并且接口的init
成员没有意义,因为您不能对interface
类型使用(后构造)对象初始化器语法。Children
is a collection property it should not have aset
accessor-仅get
-并且使用 * 协变集合接口 * 而不是具体类型(即即使用IReadOnlyList<out T>
而不是ReadOnlyCollection<T>
),这样就可以合法地将Children
作为,e.例如IEnumerable<IHierarchable>
或IReadOnlyCollection<Object?>
,而不需要不安全的强制转换或创建.ToList()
副本。使用IReadOnly...<T>
接口还意味着集合的接收者不能意外地修改它,这是软件错误的另一个常见原因。interface
。..Scene
的Scene
属性总是为null,那么将其设置为字段支持的自动属性是没有意义的--只需将其设置为始终返回null
的仅get
属性即可sealed
类,因为子类化和显式接口实现(如Scene? IHierarchable.Scene => null;
)不能很好地结合在一起。wz3gfoph2#
1.不需要显式地将
Scene
分配给null
。1.如果您仍然想指定它,可以使用属性初始化语法:
1.最后,如果两者都不适合你-重命名属性或类以摆脱显式接口实现处理:
附言
1.考虑使用nullable reference types
Scene Scene1
-〉Scene? Scene1
1.请注意,接口中的
protected
修饰符可能并不意味着您认为它的作用,请参阅默认接口方法文档的接口中的修饰符部分。