3
\$\begingroup\$

I have a FaultType enum with more than 100 members:

public enum FaultType
{
    FaultType1,
    FaultType2,
    FaultType3,
    FaultType4,
    FaultType5,
}

And I have a FaultTypeConstants class corresponding to FaultType:

public class FaultTypeConstants
{
    public const int FaultType1 = 600;
    public const int FaultType2 = 100;
    public const int FaultType3 = 453;
    public const int FaultType4 = 200;
    public const int FaultType5 = 300;
}

Now, I want to populate the List<FaultType> based on FaultTypeConstants values:

public static List<FaultType> GetFaults(List<int> FaultConstants)
{
    var faults = new List<FaultType>();
    FaultConstants.ForEach(fc => {
        switch (fc)
        {
            case FaultTypeConstants.FaultType1:
                faults.Add(FaultType.FaultType1);
                break;
            case FaultTypeConstants.FaultType2:
                faults.Add(FaultType.FaultType2);
                break;
            case FaultTypeConstants.FaultType3:
                faults.Add(FaultType.FaultType3);
                break;
            case FaultTypeConstants.FaultType4:
                faults.Add(FaultType.FaultType4);
                break;
            case FaultTypeConstants.FaultType5:
                faults.Add(FaultType.FaultType5);
                break;
            default:
                break;
        }
    });

    return faults;
}

Is there a better way to do this?

\$\endgroup\$
1
  • \$\begingroup\$ If you can't assign the ints directly in the enum, why not put it in a Dictionary<FaultType,int>? What possible reason could there be for splitting this into an enum and a Class? \$\endgroup\$ Commented Jun 10, 2014 at 15:59

2 Answers 2

3
\$\begingroup\$

You can use reflection to query the members of both types and match them by name. Something along these lines:

typeof(FaultCodes)
   .GetFields(BindingFlags.Public | BindingFlags.Static)
   .Where(fi => FaultConstant.Contains(fi.GetValue(null)))
   .Select(fi => (FaultType)Enum.Parse(typeof(FaultType), fi.Name))
   .ToList();

A way to speed it up is to build a map from code to enum. You can do this once in a static contructor:

public static class FaultLookup
{
    private static Dictionary<int, FaultType> _CodeEnumMap;
    public static FaultLoopkup()
    {
        _CodeEnumMap = typeof(FaultCodes)
                           .GetFields(BindingFlags.Public | BindingFlags.Static)
                           .ToDictionary(fi => fi.GetValue(null), 
                                         fi => (FaultType)Enum.Parse(typeof(FaultType), fi.Name))
    }

    public static IList<FaultType> GetFaultTypes(IEnumerable<int> codes)
    {
        return codes.Where(c => _CodeEnumMap.ContainsKey(c))
                    .Select(c => _CodeEnumMap[c])
                    .ToList();
    }
}

The best refactoring was mentioned by slaks though: Get rid of the implicit mapping and assign the codes directly to your enum values.

In general: Try to accept the most generic collection type possible - this will give the users of the function more flexibility regarding passing in the arguments. I find nothing more annoying than having to make a temporary collection to satisfy some interface which expects a List<T> which might not even use the fact that it's a list.

"Be liberal in what you accept and conservative in what you produce" - I find that approach quite useful not just in data processing but also for interfaces.

\$\endgroup\$
0
10
\$\begingroup\$

Get rid of the constants entirely and assign those values to the enum members themselves.
You can then use the enum everywhere.

You can cast an enum member to int to get its numeric value.

\$\endgroup\$
3
  • \$\begingroup\$ But that is not my requirement. \$\endgroup\$ Commented Oct 6, 2013 at 0:49
  • 8
    \$\begingroup\$ @PrasadKanaparthi: Why not? \$\endgroup\$ Commented Oct 6, 2013 at 1:21
  • 1
    \$\begingroup\$ list the requirement in your question please. \$\endgroup\$ Commented Oct 7, 2013 at 14:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.