Basically, I am creating a voxel-based game. I have an object Chunk with a 3 dimensional array of the object Voxel. In the array of Voxels, the Voxel currently has an isAir bool on it that signifies no voxel being there.
I am trying to add a property to Chunk which returns a 2 dimensional array of Voxel's that are on the surface of the chunk. Currently, this array will always have Voxel.isAir == false in the lower Y values and Voxel.isAir == true in the higher Y values, there is never a clear run on the "Y" axis of the array that is either all "air"s or all Voxel's, and there is never a "air" below a Voxel in the array.
To get only the "Surface" Voxel's, I have added this code to the Chunk:
public Voxel[,,] Voxels { get; set; }
private Voxel[,] _surfaceVoxels = null;
public Voxel[,] SurfaceVoxels
{
    get
    {
        if (_surfaceVoxels == null)
        {
            _surfaceVoxels = new Voxel[this.Voxels.GetLength(0), this.Voxels.GetLength(2)];
            for (var x = 0; x < this.Voxels.GetLength(0); x++)
            {
                for (var z = 0; z < this.Voxels.GetLength(2); z++)
                {
                    for (var y = 0; y < this.Voxels.GetLength(1); y++)
                    {
                        Voxel v = this.Voxels[x, y, z];
                        var solidAbove = false;
                        var solidBelow = false;
                        if (y - 1 >= 0)
                        {
                            Voxel vBelow = this.Voxels[x, y - 1, z];
                            solidBelow = !vBelow.isAir;
                        }
                        if (y + 1 < this.Voxels.GetLength(1))
                        {
                            Voxel vAbove = this.Voxels[x, y + 1, z];
                            solidAbove = !vAbove.isAir;
                        }
                        if (!v.isAir && !solidAbove && solidBelow)
                        {
                            _surfaceVoxels[x, z] = v;
                        }
                    }
                }
            }
        }
        return _surfaceVoxels;
    }
}
Calculating the surface voxels this way is computationally expensive, and i cannot see a faster way of doing this. Because of this I effectively "cache" the surface array, which is fine until the underlying 3 dimensional array is changed, as then the surface voxels will obviously need to be recalculated.
Is there some way on the get of public Voxel[,,] it only returns a clone of the array and not the array itself, and on the set set the entire array and set _surfaceVoxels to NULL, or even better is there some inexpensive way to execute code when values in an array are changed?
Is there some a more efficient way to accomplish what I have explained here that I have overlooked?
