当您需要值类型和继承时

时间:2013-05-23 08:37:34

标签: c# inheritance struct

我遇到了一些问题。

我需要类或结构来表示不同类型的顶点(TextureVertexColorVertex等)。我还需要一个超类(Vertex),因为我需要能够为任何顶点类型创建VertexBuffer。顶点必须是值类型,为什么我似乎需要一个结构。

C#中通常如何解决这种冲突?

编辑: 我需要值类型数据的原因是方法(http://sharpdx.org/documentation/api/m-sharpdx-direct3d11-buffer-create--1-1)似乎需要这种方式。它调用非托管代码,顶点数据进入数据参数。

编辑2:抛出一些代码

public interface Vertex
{ }

[StructLayout(LayoutKind.Sequential)]
public struct TextureVertex : Vertex
{
    private Vector3 _position;
    public Vector3 Position { get { return _position; } set { _position = value; } }

    private Vector2 _texture;
    public Vector2 Texture { get { return _texture; } set { _texture = value; } }

    private Vector3 _normal;
    public Vector3 Normal { get { return _normal; } set { _normal = value; } }

    public TextureVertex(float x, float y, float z, float u, float v)
    {
        _position = new Vector3(x, y, z);
        _texture = new Vector2(u, v);
        _normal = new Vector3();
    }
}

...

TextureVertex[] vertices = new []
{
    new TextureVertex(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f),
    new TextureVertex(-1.0f, +1.0f, 0.0f, 0.0f, 0.0f),
    new TextureVertex(+1.0f, +1.0f, 0.0f, 1.0f, 0.0f),
    new TextureVertex(+1.0f, -1.0f, 0.0f, 1.0f, 1.0f)
};

...

VertexBuffer = Buffer.Create<Vertex>(Graphics.Device, BindFlags.VertexBuffer, vertices);

2 个答案:

答案 0 :(得分:7)

这种要求的组合是不可能的。您可以Vertex设置一个界面(IVertex),但请注意,然后输入struct的任何IVertex都将被“装箱”。也许你最好的选择是使用泛型,即Buffer<T> where T : IVertex。只要您根据T(而不是IVertex)键入任何变量/字段/等,那么它将是 约束 ,这是说:没有盒装。在代码中使用IVertex的那一刻(除了约束中)你将获得拳击 - 所以尽量避免这种情况。

具体做法是:

T[] someBuffer = ...

T item0 = someBuffer[0]; // no box required here
item0.SomeMethodOnIVertex(); // this is a "constrained" call; no boxing

IVertex item1 = someBuffer[1]; // BOX HERE!!!
item1.SomeMethodOnIVertex(); // this is a virtual call via the box

答案 1 :(得分:1)

不,在这种情况下你不能使用继承。

顶点是值类型的原因是为了确保顶点数组(本质上是一个缓冲区)将被布局为一块连续的内存。

这样,当将底层框架发送到图形驱动程序时,它只能使用1次操作来复制它。

但是这种值类型的行为确实存在很大的局限性:Vertex的所有实例必须在内存中具有相同的大小,以便运行时可以从其索引中找到数组中的值。

但是允许在结构上继承会破坏这种期望,因为你可以将ColorVertex(带有Color数据)放在一个Vertex值数组中,因此在同一个数组中有不同大小的对象。

这种行为可以使用ref类型(想想'class'),因为在这种情况下,数组只会存储对实际内容的固定大小引用。

但这也意味着只复制数组不包含实际数据,复制实际数据需要读取数组,然后单独复制每个实例,这对3D引擎无法产生可接受的性能。