Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you define an array with a pre-specified size in C#?

Tags:

c#

.net

What I'm trying to do here should be obvious by the below code

public class RangeInfo
{
    public int[2] Range { set; }
    public string Text { set; }
}

public readonly RangeInfo[4] Ranges = new RangeInfo[4] { 
    new RangeInfo { Range = new int[2] {Int32.MinValue,70}, Text = "..." },
    new RangeInfo { Range = new int[2] {70,80}, Text = "..." },
    new RangeInfo { Range = new int[2] {80,90}, Text = "..."},
    new RangeInfo { Range = new int[2] {90,Int32.MaxValue}, Text = "..." }
};

but I'm getting tons of errors like

Array size cannot be specified in a variable declaration

on public int[2],

Expected, class, delegate, enum or struct

on RangeInfo[4]

What am I doing wrong?

like image 706
Subpar Web Dev Avatar asked Dec 02 '22 15:12

Subpar Web Dev


2 Answers

Array lengths are not part of the type signature, so the type of an array of length 2 is the same as the type of an array of length 3. The only type is int[] meaning int array of any length.

This may be confusing if you come from C++ where an array can be "in line" or a reference. In C# arrays just like other reference types are normally (unless explicitly told to be stackalloc) heap allocated, so your variable is just a pointer to an array on the heap.

If you want to constrain the size you would need to constrain it in the setter of the property (or preferably -- in the constructor of your class, since then you can make the class immutable).

public class RangeInfo
{
   public RangeInfo(IList<int> range, string txt)
   {
      if (range == null || range.Count != 2)
         throw new ArgumentException(..);
      Range = range.ToArray();
      Info = txt;
   }
   public int[] Range { get; private set; }
   public string Info { get; private set; }
}

However, with this type of construction I'd rather just pass in two ints to the ctor, and have two int fields (That way you don't have to heap allocate an array).You could also use a tuple or declare an int pair class. You could still expose the two internal int fields as an array by returning new[]{a,b}.

As an aside: fixed size arrays do exist in C#, but mainly for interop. It would be pretty silly to declare structs like this in order to call some C API that wants 64 consecutive 32bit ints:

struct FooStruct
{
    int int0;
    int int1;
    ..
    int int63;
}

So instead it's possible to create a fixed int[64] which just emulates the above.

[StructLayout(LayoutKind.Sequential, Pack = 1)]
unsafe struct FooStruct
{
    fixed int[64] data;
}
like image 68
Anders Forsgren Avatar answered Feb 14 '23 09:02

Anders Forsgren


Length is a property of an array instance, not part of the type. An array variable merely contains a pointer to an array. Therefore fields, properties, and other variable declarations are agnostic of the length. You can only specify the length when instantiating an array, not when declaring variables.

If you need your arrays to have a particular length, your property setters can check the length at runtime and throw an exception if the length is wrong. However, there is no way to enforce this at compile time.

A more maintainable solution might be to not use arrays at all, and instead create a class with a separate property for each value currently represented in your arrays. This assumes that the values at particular indices have different meanings. If the array really is representing just a set of values, then you're probably better off using a List. See https://en.wikipedia.org/wiki/Zero_one_infinity_rule

like image 27
hypehuman Avatar answered Feb 14 '23 08:02

hypehuman