4

I currently have a Match struct which contains a list of Blocks.

public struct Match{
    public List<Block> blocks;
}

When I try to create a new Match (in this case, called matchData) and add Blocks to its Block list, my compiler outputs:

Use of unassigned local variable 'matchData'

I tried initializing the list by doing this:

public struct Match{
    public List<Block> blocks = new List<Block>();
}

which results in the following error:

Structs cannot have instance field initializers

So how should I initialize my Match struct? Do I have to make a constructor?

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
TheYokai
  • 341
  • 5
  • 10
  • 2
    Why are you using a struct instead of a class? – Blorgbeard Jun 13 '14 at 04:15
  • I have made a struct for two other reasons: 1) Matches may contain other data, like which direction the match has been made and which block is the lowest in the block grid. 2) There will also be a list of matches, so it would basically be a nice way of having a list of lists that are sorted in a particular way. There's no reason why I couldn't use a constructor, I guess I asked it that way to make sure I wasn't overlooking something. I'm not used to structs in C# yet as they seem different than other programming languages I'm more familiar with. – TheYokai Jun 13 '14 at 04:38
  • 1
    None of the above precludes you using a class instead of a struct. If you're not familiar with structs in C#, you should be careful. Structs are value types, which changes how they behave in sometimes unintuitive ways. And structs are supposed to be quite small and simple. Your "Match" entity sounds more like a class to me. Have a look at [these guidelines](http://msdn.microsoft.com/en-us/library/ms229017.aspx). – Blorgbeard Jun 13 '14 at 04:47

2 Answers2

5

From MSDN:

It is also an error to initialize an instance field in a struct body. You can initialize struct members only by using a parameterized constructor or by accessing the members individually after the struct is declared. Any private or otherwise inaccessible members can be initialized only in a constructor.

http://msdn.microsoft.com/en-us/library/0taef578.aspx

So you can initialize the list in a parameterized constructor like so:

public struct Match{
    public List<Block> blocks;
    
    public Match(List<Block> blocks)
    {
        this.blocks = blocks;
    }
}

Or set it from the outside:

Match m = new Match();
m.blocks = new List<Block>();

As a side note, you probably would be better off using a class instead of a struct here. Your use doesn't seem to fit the typical use-case, as indicated here: http://msdn.microsoft.com/en-us/library/ah19swz4.aspx

Arialdo Martini
  • 4,427
  • 3
  • 31
  • 42
Mike Hixson
  • 5,071
  • 1
  • 19
  • 24
4

You were getting "Use of unassigned local variable 'matchData'" because you didn't call new Match():

Match matchData;
matchData.blocks = new List<Block>();    // error!

But:

Match matchData = new Match();
matchData.blocks = new List<Block>();    // fine!

Structs have an implicit parameterless constructor which initializes all fields to default values.

However: You should be using class instead of struct, unless you understand exactly how structs work in C#. Do not just use struct because it's "lighter" than a class.

In particular, your Block struct is mutable, which makes for a bad time.

Community
  • 1
  • 1
Blorgbeard
  • 101,031
  • 48
  • 228
  • 272