gpt4 book ai didi

C# 抽象结构

转载 作者:可可西里 更新时间:2023-11-01 08:55:24 24 4
gpt4 key购买 nike

如何在 C# 中使用结构实现继承(或类似继承)?我知道抽象结构是不可能的,但我需要实现类似的目标。

我需要它作为一个结构体,因为它必须是一个值类型。我需要继承,因为我需要一个通用数组和我可以保证的方法。

我认为一个例子会有很长的路要走,所以这里有一些代码无法编译,但显示了我想要实现的目标;

    abstract struct Vertex
{
abstract int SizeInBytes;
abstract void SetPointers();
}
struct ColorVertex : Vertex
{
Vector3 Position;
Vector4 Color;

override int SizeInBytes //static
{
get { return (3 + 4) * 4; }
}
override void SetVertexPointers() //static
{
...
}
}

class main
{
static void main()
{
Vertex[] verts = new Vertex[3];
for(int i = 0; i < 3; i++)
verts[i] = new ColorVertex();

verts[0].SetVertexPointers(); //should call ColorVertex.SetVertexPointers

externalAPIcall(verts);
}
}

编辑:

我需要值类型的原因是我可以将它们组成一个数组,并将它作为顶点缓冲区传递给 OpenGL。为此,数据需要直接包含在此数组中。

如果这根本不可能实现,我会感到惊讶。

最佳答案

根据您最近的修改:

The reason I need value types is so that I can make an array of them, and pass it to OpenGL as a vertex buffer. For this, the data needs to be directly contained in this array.

看起来真正的解决方案对您来说是封装。如果您的 struct 的布局由第三方 API 指定(以便您可以与非托管代码交互),那么您真的应该考虑将 API 类型包装在适当的类中,而不是尝试与他们直接在代码中。

首先,您声明:

I need it as a struct because it has to be a value type. And I need inheritance because I need a generic array and methods that I can garantee are there.

结果不会像您期望的那样。正如其他人指出的那样,定义一组可应用于结构的通用功能的唯一方法是通过接口(interface)(例如,.NET 中的基本类型实现 IComparable)。不幸的是,如果您要声明 IYourInterface 类型的数组,所有值都将被装箱(接口(interface)引用是引用类型,即使它们指向的基础值是值类型)。

例如,假设您声明了一个 IVertex 接口(interface):

public interface IVertex
{
int SizeInBytes { get; }
void SetPointers();
}

并且您有一个或多个实现它的值类型:

struct ColorVertex : IVertex
{
Vector3 Position;
Vector4 Color;

override int SizeInBytes //static
{
get { return (3 + 4) * 4; }
}
override void SetVertexPointers() //static
{
...
}
}

每当你这样做时:

ColorVertex myVertex = new ColorVertex();

IVertex foo = myVertex;

第二行将装箱 myVertex 的值并将对该装箱值的引用存储在 foo 中。由于数组只是一系列变量,因此适用相同的规则:

IVertex[] foos = { myVertex };

foos 中的所有值都将被装箱,并存储它们的引用。这与您所做的不同:

ColorVertex[] colors = { myVertex };

不需要装箱的地方。

这与您正在寻找的内容直接相关,因为装箱值现在意味着您不再拥有连续的值 block (好吧,您有,但连续 block 只是引用资料;值(value)本身位于其他地方)。

封装

鉴于你

  1. 拥有您需要与之交互的已定义类型的第三方 API
  2. 需要在您的代码中支持不同的用例,并希望使用面向对象的设计模式来实现这一点

您真的应该考虑包装 OpenGL API。例如,假设您有以下内容:

// OpenGL type
struct Vertex
{
int SizeInBytes;
}

public static extern void OpenGLFunction(Vertex[] vertices);

可能更好的选择是定义您自己的界面,然后隐藏 OpenGL API:

public abstract class VertexBase
{
internal Vertex ToVertex()
{
// your logic here
}
}

public static class OpenGL
{
public static void WrappedFunction(VertexBase[] vertices)
{
Vertex[] outVertices = new Vertex[vertices.Length];

for(int i = 0; i < vertices.Length; i++)
{
outVertices[i] = vertices[i].ToVertex();
}

OpenGLFunction(outVertices);
}
}

(这显然是一个人为的示例,但它应该展示我在您的代码和其他 API 之间引入抽象层方面试图传达的内容)

关于C# 抽象结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5007947/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com