KansaiRobot
KansaiRobot

Reputation: 9912

Constant array of constant objects in C#

I am aware that in C# const can only be initialized at compile time. Which is related to what I am trying to do.

My objective is to write a constant array of constant objects in C#. How can I do that?

In order to explain my self, allow me to insert some code in C++ (I wrote some code some time ago) that explains what I am trying to do.

(In C++)

struct FD{
 string name; 
 double CE[2]; 
};

const FD models[2]={
     {"one",{2.0,1.0}},
     {"two",{3.0,4.0}}
};

Seems very simple, right? How can I do something like this in C#?


EDIT: (Attempted answer)

I found that you can do something like this in C#

 struct FD
    {
        public string name;
        public double[] CE;
    }
 static readonly FD[] models= new[]
   {
     new FD(){name="one" , CE= new double[]{1.0,2.0 } },
     new FD(){name="two", CE= new double[]{3.0,4.0}}         
   };

I wonder if this could be a good way to achieve my objective?

Upvotes: -1

Views: 4141

Answers (3)

KansaiRobot
KansaiRobot

Reputation: 9912

In the end thanks to users Corak and Freggar I could come with something like this. (I suppose that model3 is the answer

Structs

 struct FD
    {
        public string name;
        public double[] CE;
    }

    struct FD2
    {
        public FD2(string name, IEnumerable<double>ce)
        {
            Name = name;
            CE = new ReadOnlyCollection<double>(new List<double>(ce));
        }
        public readonly string Name;   
        public readonly IReadOnlyList<double> CE;
    }

and the lists

 //This solution does not give the entire constant structure as name and FD[0] can be changed
        static readonly FD[] models= new[]
          {
              new FD(){name="one" , CE= new double[]{1.0,2.0 } },
              new FD(){name="two", CE= new double[]{3.0,4.0}}

          };

        //Here name can not be changed but models2[0] can be
        static readonly FD2[] models2 = new[]
        {
            new FD2("one",new double[]{1.0,2.0 }),
            new FD2("two", new double[]{3.0,4.0 })
        };

        //This is the best solution
        static readonly IReadOnlyList<FD2> models3 = new ReadOnlyCollection<FD2>(new[] {
            new FD2("one",new double[]{1.0,2.0 }),
            new FD2("two", new double[]{3.0,4.0 })
        }
        );

        //This is also a good solution but models4[0].CE[0] can be changed
        static readonly ReadOnlyCollection<FD> models4 = new ReadOnlyCollection<FD>(new[]
        {
             new FD(){name="one" , CE= new double[]{1.0,2.0 }},
             new FD(){name="two", CE= new double[]{3.0,4.0}}
        }); 

I guess models3 gives a good implementation to what I wanted to achieve.

Upvotes: -1

Freggar
Freggar

Reputation: 1056

Sadly in C# you cannot define arrays or structures as const since the constructor can have runtime logic and therefore has to be executed at runtime. Your proposed solution is almost what you want, you just need a ReadonlyCollection<FD> to encapsulate your Array:

using System.Collections.ObjectModel;

static readonly ReadOnlyCollection<FD> models = new ReadOnlyCollection<FD>(new[]
{
    new FD(){name="one" , CE= new double[]{1.0,2.0 } },
    new FD(){name="two", CE= new double[]{3.0,4.0}}
});

Now you cannot change the reference of models (readonly) nor can you change the contents of it (ReadonlyCollection). You also cannot change any members of the FD instances since FD is a struct and the ReadonlyCollection creates another layer of indirection, basically copying your struct:

models = new ReadOnlyCollection<FD>(new FD[] { }); // Error CS0198  A static readonly field cannot be assigned to
models[0] = new FD(); // Error CS0200  indexer  is read only
models[0].name = "testname"; // Error CS1612  Cannot modify the return value

EDIT : I overlooked something, you can still change the array:

 models[0].CE[0] = 1; // compiles just fine

If possible you want to make CEreadonly too, but I'm not sure if your API allows that

Upvotes: 2

tmaj
tmaj

Reputation: 34967

Thinking outside the box :P

Others are providing you with great ideas but if you want to have truly const 4 values then you could just:

    const double FD_one_0 = 2.0;
    const double FD_one_1 = 1.0;
    const double FD_two_0 = 3.0;
    const double FD_two_1 = 4.0;

Upvotes: 1

Related Questions