Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

c# arrays in nested structs

I am trying to build a simulation in C#.
The model itself I want to adress as a struct. Inside the model are a lot of elements (I refer to them as cells, considering that elements also refer to the chemical elements in my program and that is confusing)
Each cel is a struct. One of the data types inside is an array of floats.

Below is the code I wrote:

struct Model
{
    //model consists of an array of cells
    public Cel[] cel = new Cel[100];

    public Model() { }
}
struct Cel
{
    public float[] n = new float[3];
    public Cel() { }
}


class Programs
{
    static int Main()
    {
        Model model = new Model();

        model.cel[1].n[1] = 0.2f;
        Console.WriteLine(model.cel[1].n[1]);

        //prevent console from closing
        Console.ReadLine();

        return 0;
    }
}

When I run this, it compiles, but gives a message:
System.NullReferenceException: ‘Object reference not set to an instance of an object.’
model.cel[].n was null. at line 24
model.cel[1].n[1] = 0.2f;

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I think this is a logical way to do this and would like a solution to make it work.
If this is not the way to do it, could someone point me in the right direction?

Thank you for your help.

>Solution :

Array creation does not initialize each element inside the array – they are all defaults; you could do something like:

    public Cel[] cel;

    public Model() {
        cel = new Cel[100];
        for (int i = 0; i < cel.Length; i++)
        {
            cel[i] = new Cel();
        }
    }

to initialize each manually, but… I’m not sure this is a great outcome, honestly. In particular, instead of a float[3], having 3 discreet float fields in the Cel struct would be a more typical implementation, perhaps making Model a class. You should also usually be very cautious of public fields and mutable structs.

Perhaps something like:

sealed class Model
{
    //model consists of an array of cells
    private readonly Cel[] cel = new Cel[100];

    public ref Cel this[int index] => ref cel[index];
}
readonly struct Cel
{
    public float X { get; }
    public float Y { get; }
    public float Z { get; }
    public Cel(float x, float y, float z)
    {
        X = x;
        Y = y;
        Z = z;
    }

    public Cel WithX(float x) => new Cel(x, Y, Z);
    public Cel WithY(float y) => new Cel(X, y, Z);
    public Cel WithZ(float z) => new Cel(X, Y, z);
}
class Programs
{
    static int Main()
    {
        Model model = new Model();

        ref var cel = ref model[1];
        cel = cel.WithY(0.2f);

        Console.WriteLine(model[1].Y);

        //prevent console from closing
        Console.ReadLine();

        return 0;
    }
}

or with a fixed buffer and span hack:

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

sealed class Model
{
    //model consists of an array of cells
    private readonly Cel[] cel = new Cel[100];

    public ref Cel this[int index] => ref cel[index];
}
unsafe struct Cel
{
    private fixed float n[3];
    public float X => n[0];
    public float Y => n[1];
    public float Z => n[2];
    public Span<float> N
    {
        get
        {
            fixed (float* ptr = n)
            {
                return MemoryMarshal.CreateSpan(ref Unsafe.AsRef<float>(ptr), 3);
            }
        }
    }
    public Cel(float x, float y, float z)
    {
        fixed (float* ptr = n)
        {
            ptr[0] = x;
            ptr[1] = y;
            ptr[2] = z;
        }
    }

    private Cel(in Cel from, int index, float value)
    {
        this = from;
        n[index] = value;
    }

    public Cel WithX(float x) => new Cel(this, 0, x);
    public Cel WithY(float y) => new Cel(this, 1, y);
    public Cel WithZ(float z) => new Cel(this, 2, z);
}
class Programs
{
    static int Main()
    {
        Model model = new Model();

        ref var cel = ref model[1];
        cel = cel.WithY(0.2f);

        Console.WriteLine(model[1].Y);

        Console.WriteLine();
        foreach (var val in model[1].N) // and iterate via span
        {
            Console.WriteLine(val);
        }

        //prevent console from closing
        Console.ReadLine();

        return 0;
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading