1. The Vertex

A Vertex (pl. Vertices) specifies a number of Attributes associated with a single Point in space. In the fixed-function environment a Vertex commonly includes Position, Normal, Color and/or Texture Coordinates. The only Attribute that is not optional and must be specified is the Vertex's Position, usually consisting of 3 float.
In Shader Program driven rendering it is also possible to specify custom Vertex Attributes which are previously unknown to OpenGL, such as Radius or Bone Index and Weight for Skeletal Animation. For the sake of simplicity we'll re-create one of the Vertex formats OpenGL already knows, namely InterleavedArrayFormat.T2fN3fV3f. This format contains 2 float for Texture Coordinates, 3 float for the Normal direction and 3 float to specify the Position.

Thanks to the included Math-Library in OpenTK, we're allowed to specify an arbitrary Vertex struct for our requirements, which is much more elegant to handle than a float[] array.

[StructLayout(LayoutKind.Sequential)]
struct Vertex
{ // mimic InterleavedArrayFormat.T2fN3fV3f
  public Vector2 TexCoord;
  public Vector3 Normal;
  public Vector3 Position;
}

This leads to a Vertex consisting of 8 float, or 32 byte. We can now declare an Array of Vertices to describe multiple Points and allow easy indexing/referencing them.

Vertex[] Vertices;

The Vertex-Array Vertices can now be created and filled with data. Addressing elements is as convenient as in the following example:

Vertices = new Vertex[ n ]; // -1 < i < n  (Remember that arrays start at Index 0 and end at Index n-1.)
 
// examples how to assign values to the Vector's components:
Vertices[ i ].Position = new Vector3( 2f, -3f, .4f ); // create a new Vector and copy it to Position.
Vertices[ i ].Normal = Vector3.UnitX; // this will copy Vector3.UnitX into the Normal Vector.
Vertices[ i ].TexCoord.X = 0.5f; // the Vectors are structs, so the new keyword is not required.
Vertices[ i ].TexCoord.Y = 1f;
 
// Ofcourse this also works the other way around, using the Vectors as the source.
Vector2 UV = Vertices[ i ].TexCoord;

An Index is simply a byte, ushort or uint, referencing an element in the Vertices Array. So if we decide to draw a single Vertex 100 times at the same spot, instead of storing 100 times the same Vertex in Vertices, we can reference it 100 times from the Indices Array:

uint[] Indices;

Basically the Indices Array is used to describe the primitives and the Vertex Array is used to declare the corner points.

We can also use collections to store our Vertices, but it's recommended you stick with a simple Array to make sure your Indices are valid at all times.
Now the Vertices and Indices Arrays can be used to describe the edges of any Geometric Pritimitve Type.

Once the Arrays are filled with data it can be drawn in Immediate Mode, as Vertex Array or sent into a Vertex Buffer Object.