2

I've trying to work with a struct (for the first time) and have come up with a slight issue I don't know how to work around.

public struct TextSelect<TEnum> where TEnum : Enum
{
    public TextSelect(string input = "")
    {
        Input = input;
        Values = EnumDto.ToList<TEnum>();
    }

    public string Input { get; set; }
    public IEnumerable<EnumDto> Values { get; }
}

public TextSelect<IndustryType> Industry = new TextSelect<IndustryType>();

The problem relates to parameterless constructors.

I would like to initialize the Values property when the struct is instantiated, but TEnum is a type, not an instance value, so it doesn't count as a parameter.

As such, I get an compiler warning if the constructor has no parameters.

If I add an optional value, 'Input', I can trick the compiler and warning disappears, but the constructor still doesn't fire (presumably because it's empty).

Other than change it to a class, are there any other workarounds?

All advice appreciated.

John Ohara
  • 2,821
  • 3
  • 28
  • 54
  • Can you check this workaround ? https://stackoverflow.com/a/433233/2770248 – Thirueswaran Rajagopalan Jun 10 '19 at 07:03
  • Why do you want it to be a struct? There are very few occasions where structs make sense, and yours seems not to be one of them. Structs can be stored on the stack, but since your struct contains reference types as properties (`IEnumerable`, `string`), the heap is involved anyhow. – Heinz Kessler Jun 10 '19 at 07:03
  • The fact that you have a `set` on this `struct` *already* tells me that you're in very very dangerous water here. Why are you trying to make this as a `struct`? – Marc Gravell Jun 10 '19 at 07:03
  • "but the constructor still doesn't fire" - with `new TextSelect()` (or `default`), the implicit default initializer (just an "all zero" blit) will be a better match than using the optional parameter, so the default initializer will be used. – Marc Gravell Jun 10 '19 at 07:05
  • Thanks for your input guys. When I'm told "you in very very dangerous water" from Marc Gravell, I know it's a bad approach. I'll ditch it! – John Ohara Jun 10 '19 at 07:12
  • @JohnOhara in all seriousness, if I had a penny for every question here that is essentially "I wrote a mutable struct, and now weird things are happening - why?" - then I'd have... well... *muchos muchos* pennies – Marc Gravell Jun 10 '19 at 07:18
  • @MarcGravell - I really appreciate your advice Marc - saved me hours exploring the stupid route. Where do I send the penny? – John Ohara Jun 10 '19 at 07:32

1 Answers1

0

For the parameterless constructor - there is no way to make it fire. In C# structure's fields are always initialized with default values.

There are workarounds though. If you are really commited to keeping this as a struct and want the field to return a different value by default I would recommand converting Values to full property and returning the desired value if field was not initialized:

private IEnumerable<EnumDto> _values;
public IEnumerable<EnumDto> Values => _values ?? Array.Empty<EnumDto>();

That being said it's not exactly the best practice to do so with structures.

Edit: changed the solution by @Marc Gravell suggestion.

  • 1
    Observation: this will create a new list *every time the property is accessed* (when the field is null) - not a good idea; `=> _values ?? Array.Empty();` would be much better – Marc Gravell Jun 10 '19 at 07:20