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;
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.
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;
}
}
You haven't initialized a Cel yet. You have only reserved space in the array, but it is still empty.
Try this:
model.cel[1] = new Cel();
model.cel[1].n[1] = 02f;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With