从c#中inheritance结构的梦想

在那里,我正在使用C#XNA 4.0进行2D游戏,并再次遇到我的小烦恼; 矩形 。 对于那些使用基本碰撞的人来说,这几乎是必需的。 对于几乎所有创建的游戏对象,您需要有一个矩形。 然后我去改变X,检查碰撞或其他任何东西。 在那里,我开始了objectName.Rectangle.Whatever的永无止境的战斗。 为了解决这个问题,我当然会给出一些objectName属性/方法来为我访问这些属性/方法。

然后我敢于梦想。 我有一个伟大的设计来制作一个基本的游戏对象类,所有drawable将inheritance,这将允许父母,精确的本地坐标(浮点数),并保持纹理/ spritebatch。 为了完成这个,我准备从Rectangleinheritance,使用它所拥有的所有方法和属性。 哎呀,每当需要一个Rectangle的东西时,我可能会懒得说objectName,而不是objectName.Rectangle。

然后我意识到,不是机会。 我开始感到沮丧,因为我很聪明的想法被砸碎了。 从那以后,我完美的小class级拥有一个矩形,各种方法和属性根据需要访问它。 我也有机会从XNA DrawableGameComponentinheritance它。 虽然从长远来看这更实用,每次我查看绘制或更新方法并看到我经常想到的矩形调用时,是否有希望做我想要的事情? 我可以做一些聪明的工作吗? 或者是从一个真正被我掌握的矩形inheritance而来?

虽然使用XNA中提供的DrawableGameComponent类允许大多数与游戏对象相关的操作发生在类Update()方法中,但每次在类之外我都需要引用而不是Rectangle的属性,而是Rectangle本身,我稍微考虑到实际上我的对象实际上是各种方式,并且加强了Rectangle。 然后我再一次发现自己在问:

有没有办法从预定义的结构inheritance,或者给项目留下你的印象(一种解决方法)?

inheritance否,但您可以使用扩展方法向Rectangle对象添加许多“默认”function。 例如

  //(inside a static class) public static int GetSurface(this Rectangle rect){return rect.Width * rect.Height;} //calling Rectangle rect; var s = rect.GetSurface(); 

也就是说,我通常做的是封装所述结构。 使用该类作为基础对象,并添加一个运算符,以便可以隐式转换为Rectangle。 这样它就可以传递给一个需要一个矩形而不需要强制转换的方法。

  public class MyRect //class so you can inherit from it, but you could make your own struct as well { public int X { get; set; } public int Y { get; set; } public int Width { get; set; } public int Height { get; set; } public int Right { get { return X + Width; } } public int Bottom{ get { return Y + Height; } } public static implicit operator Rectangle(MyRect rect) { return new Rectangle(rect.X, rect.Y, rect.Width, rect.Height); } public static implicit operator MyRect(Rectangle rect) { return new MyRect { X = rect.X, Y = rect.Y, Width = rect.Width, Height = rect.Height }; } } } 

现在,您可以手动或从现有的rect创建自己的rect:

  MyRect rect = ARectangleVar 

并且您可以在遗留方法中使用它,这些方法需要一个不转换的Rectangle

这是一个可能的解决方法(把它放在MyClass ,你所说的具有Rectangle属性的类):

 public static implicit operator Rectangle(MyClass obj) { return obj.Rectangle; } 

这将允许您将对象传递给期望Rectangle的方法,并且它可以工作。 请注意,与真正的inheritance不同,存在的Rectangle与传入的MyClass实例不同,它只是由值构成的结构。

值类型从根本上与适用于类类型的inheritance风格不兼容,但是能够以这样的方式声明“派生结构”将有助于编译器识别派生之间的双向身份保留转换。类型和原始。 派生的结构将需要只有一个字段,称为“Base”(尽管C#编译器可以接受关键字base作为替代),其类型是派生的结构的类型。 名称与周围类型的名称不匹配的“Base”的所有成员将被视为封闭结构的成员。

“派生结构”提供的主要内容,但目前缺乏的主要内容是:

  1. 能够访问包装结构的成员而无需添加额外的语法间接层。 例如,如果有一个实例`MyFancyPoint`是从`Point`中剔除的类型,可以说`MyFancyPoint.X + = 5`而不是’MyFancyPoint.Base.X + = 5`。
  2. 能够一次执行多个隐式或显式类型转换。 C#通常只允许从“X”转换为“Y”,除非存在直接转换,部分原因是搜索所有可能的转换序列很困难,部分原因是这样做通常会产生关于转换序列的模糊性应该受雇。 如果假定包装特定结构的所有类型都表示具有突变身份保留转换的“云”,则两个派生结构“XX:X”和“YY:Y”之间的转换可以毫不含糊地视为转换为“X” ,然后是“Y”,然后是“YY”(如果存在“X”到“Y”转换,那将是合法的)。
  3. 能够将ByRef作为ByRef的一个类型的实例视为另一个的实例,将ByRef视为一个字段的ByRef,将其视为另一个字段中相应字段的ByRef。

我不确定是否需要对运行时进行任何更改以支持任何这些function,如果接受盒装派生类型的项目只能将其取消装箱为同一派生类型; 允许将框架版本的结构直接转换为身份可转换派生的实例,这将有所帮助,但可能会增加复杂性。 我不确定是否需要这样的行为来使generics工作。 不幸的是,我觉得许多负责做出这种决定的人真的不喜欢价值类型。 由于.net历史早期的一些设计决策(特别是缺少“const ref”参数和通过ref公开属性的方法),使结构以语义正确的方式工作可能是一个挑战,我想一些实现者宁愿使用结构的问题作为不改进.net处理它们的借口,而不是添加能解决问题的function。