简体   繁体   中英

How to declare an array of structs inside a struct?

Using Visual Studios 2010 C#

so i am making a struct of data for ac# project, that will among it's members include an array of type another struct. So for example here is a stripped down idea of my code:

    private struct scores
    {

        public double finalScore;


    };

    private struct information
    {
        public string name;
        public scores[] scoreList;

    };

I am getting the following warning when I write this:

Error 1 'WindowsFormsApplication1.main.information.scoreList': cannot have instance field initializers in structs

I am wondering what is the correct way to declare the scores[] scoreList aspect of the struct information, so I can have the array size set to 10?

Things I have tried:

  • If I try

    public scores[] scoreList = new scores[10]

I get the following error

Error 1 'WindowsFormsApplication1.main.information.scoreList': cannot have instance field initializers in structs

The problem here is that you're making the structs private, which means you can't make instances of them. Make them public. And also get rid of the ; at the end

public struct scores
{

    public double finalScore;


}

public struct information
{
    public string name;
    public scores[] scoreList;

}

I typically don't use structs because of their OO limitations and the fact that they're not nullable. There are however several structs in .Net : DateTime, int, float etc...

In structs you can do initialization within constructors only:

  struct information {
    public string name;
    public scores[] scoreList;

    // Constructor
    public information(String nameValue) {
      name = nameValue;
      scoreList = new scores[10]; // <- It's possible here
    }
  };

You can't do this. The reason is that structs are value types. The default constructor of a struct is a parameterless constructor that initializes all fields to their default value. You don't have control over this constructor because they are value types.

The best way to show this is eg through an array. Say you make an array of aa class type, eg new object[10] . The items of this array will be initialized to null . However, when you would make an array of structs, eg new information[10] , the items of the array will be valid instances already. However, the constructor on these items won't have run and all fields will have been initialized to their empty values. In your case, this means that all fields will be null .

There are two solutions to this. The first solution is to create a factory method, eg:

public static information CreateNew()
{
    var result = new information();
    result.scoreList = new scores[10];
    return result;
}

This will work. You just create an instance with information.CreateNew() instead of new information() , and you will have an initialized information . However, a far more easy solution will be to just use a class instead.

There are three ways to have a structure behave as a value-type array of structs:

  • Use unsafe code to include one or more fixed arrays of primitives within your structure; have your indexed get/put accessors assemble a structure out of information stored in those arrays. For example, if you wanted to behave like an array of Point , one could have a fixed array for all the X coordinates and a fixed array for all the Y coordinates, and then have the this[int] getter construct a Point by combining an X and Y value, and the this[int] setter store the X and Y values from the passed-in point.
  • Have multiple fields of your struct type, and have the this[int] getter read from one of them and have the this[int] setter write to one of them. There are ways by which this can be made not too horribly inefficient, but it's still rather icky.
  • Have the structure hold a private array of the appropriate structure type. The get and set accessors should look something like:

     T[] _array; T this[int index] { get { T[] temp_array = _array; if (temp_array == null) return default(T); return temp_array[index]; } set { do { T[] was_array[] = _array; T[] new_array = (temp_array == null) ? new T[size] : (T[])(temp_array.Clone()); temp_array[index] = value; } while (System.Threading.Interlocked.CompareExchange(ref _array, new_array, was_array) != was_array); }}; 

    This approach will allow the get indexer to run faster than would be possible with the second approach (and probably the first as well), and unlike the first approach it will work with generic types. The primary weakness with this approach is that every time its set accessor is run it must make a new copy of the array. If writes are much less frequent than reads, however, that might not be a problem. Incidentally, as written, the code should be fully thread-safe--something which is possible with mutable structures, but not possible with structures that pretend to be immutable.

  • The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

     
    粤ICP备18138465号  © 2020-2024 STACKOOM.COM