0

I have a struct for a game I am building that looks like this:

using System;

public readonly struct Target
{
    public Target((int Min, int Max) range, string[] targetTypes)
    {
        Range = range;
        TargetType = ParseTypes(targetTypes);
    }
    public (int Min, int Max) Range { get; }
    public TargetTypes TargetType { get; }
    [Flags]
    public enum TargetTypes { None = 0, Self = 1, Enemy = 2, Player = 4, Character = 8, Area = 16 }
}

I would like to take all of the values in the string array and cast them into a single enum (not an array of enum values, which I believe is what is happening in the answer to this question).

The thing is a Target can have multiple types. I figured an enum was the best way to represent this, and also figured defining the enum inside the struct wasn't a terrible idea, but this could be an anti-pattern (coming from a JS background, be gentle!).

I like this whole enumeration types as bit flags thing, hence the numbering, that's what sent me down this path.

Yes, I control the inputs, so happy to hear why/how I should do this differently - thanks for your time!

GrayedFox
  • 2,350
  • 26
  • 44
  • If you do a string.join with a comma separator Enum.TryParse should work. https://learn.microsoft.com/en-us/dotnet/api/system.enum.tryparse?redirectedfrom=MSDN&view=netcore-3.1#System_Enum_TryParse__1_System_String___0__ see also https://stackoverflow.com/questions/2745320/enum-tryparse-with-flags-attribute – asawyer Oct 30 '20 at 01:57
  • Could you flesh that out into an example good sir? I am trying `TargetType = Enum.TryParse(String.Join(",", targetTypes), out TargetType);` without any luck – GrayedFox Oct 30 '20 at 02:06
  • I was away for a bit and looks like @AnyViswan chimed in. Thanks! – asawyer Oct 30 '20 at 02:28

2 Answers2

1

You could use the following.

TargetType = (TargetTypes)Enum.Parse(typeof(TargetTypes),string.Join(",",targetTypes));

The second parameter of Enum.Parse accepts either a single value/constant representing the enum or a list of named constants or underlying values delimited by commas (,).

Anu Viswan
  • 17,797
  • 2
  • 22
  • 51
0

Thank you @asawyer for pointing the way. I missed an important part of the documentation (always RFTM twice!):

Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object.

There's no need for anything fancy here, Parse does the trick:

TargetType = (TargetTypes) Enum.Parse(typeof(TargetTypes), string.Join(",", targetTypes));

GrayedFox
  • 2,350
  • 26
  • 44
  • 1
    fyi there's a generic version of this call - https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse?view=netcore-3.1#System_Enum_Parse__1_System_String_ which would reduce your code to `TargetType = Enum.Parse(string.Join(",", targetTypes));` No explicit casts or `typeof` needed. – asawyer Oct 30 '20 at 02:28
  • 1
    Honestly though since your input is just strings you have no guarantee the caller will provider the expected input which leaves you with two problems - What if the input can parse to an integer that is not a valid enumeration / flag combination? What if the input cannot be parsed at all? In the first case, if it can parse to the input to integer it will happily. Try with the value "123" instead of an enum value string. You'll get a `Target` back with the value 123, which is not defined in the enumeration. In the other case you'll get an ArgumentException thrown. – asawyer Oct 30 '20 at 02:54
  • -- continuing - If it where me, I'd simply have the constructor accept the enum value directly and push this task off to a dedicated enum parsing section, or into an load/save serialization type section. Why should a `Target` structure be involved in string parsing in the first place? – asawyer Oct 30 '20 at 02:56
  • All very good input, thank you! I will certainly consider defining the enum and doing that parsing somewhere dedicated! – GrayedFox Oct 31 '20 at 11:52