-1

I am trying to implement a generic method for values that provide Parse and ParseExact methods. Types for which my method should work, are value types (like double, int etc.) and TimeSpan.

Any ideas how I can implement what I describe?

To understand better what I need, I made some code that roughly depicts what I would like to achieve (obviously it doesn't work). Flags is just some enum.

public Dictionary<Flags, object> FlagValues { get; } = new Dictionary<Flags, object>();

public T GetFlagValue<T>(Flags flag, string formatString = null) where T : struct
{
    T result = default(T);
    if (FlagValues.TryGetValue(flag, out object flagValueRaw))
    {                
        if (formatString == null)
        {
            result = T.Parse(flagValueRaw, CultureInfo.InvariantCulture);
        }
        else
        {
            result = T.ParseExact(flagValueRaw, formatString, CultureInfo.InvariantCulture);
        }
    }
    return result;
}
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
gryz
  • 48
  • 4
  • 3
    when thinking about *generics* you should ask yourself: what do the types have in common? What is common about `TimeSpan`, `int` and `double`, but not for let's say `bool`? There's nothing common between them, so generics aren't the right thing. See this related question: https://stackoverflow.com/questions/32664/is-there-a-constraint-that-restricts-my-generic-method-to-numeric-types. If you however want to make a generic method for **all** value-types, `where T: struct` should do it. – MakePeaceGreatAgain Sep 22 '21 at 08:59
  • 3
    You cant constrain a generic method to arbitrary logic, you will need to rethink your problem – TheGeneral Sep 22 '21 at 09:02
  • 1
    The `Try...`-methods are unique to the classes they belong to. In particular they are all `static`, so there is no inheritance-chain involved here which you could use for some common base-class. I'm afraid you need different methods for each type you want to handle. – MakePeaceGreatAgain Sep 22 '21 at 09:07
  • 1
    Also *"like double, int etc"* don't have `ParseExact` methods anyway – TheGeneral Sep 22 '21 at 09:09

1 Answers1

0
    // Error handling not included
    // Since the first parameter is string in all Parse, ParseExact.
    public Dictionary<Flags, string> FlagValues { get; } = new();

    public T GetFlagValue<T>(Flags flag, string? formatString = null) where T : struct
    {
        if (FlagValues.TryGetValue(flag, out var flagValueRaw))
        {
            if (!string.IsNullOrEmpty(formatString))
            {
                var parseExact = typeof(T).GetMethod("ParseExact", new[] { typeof(string), typeof(string), typeof(IFormatProvider) });

                if (parseExact is not null)
                return (T)parseExact.Invoke(null, new object?[] { flagValueRaw, formatString,  CultureInfo.InvariantCulture })!;
            }
            var parse = typeof(T).GetMethod("Parse", new[] { typeof(string), typeof(IFormatProvider) })!;
            if (parse is not null)
                return (T)parse.Invoke(null, new object?[] { flagValueRaw, CultureInfo.InvariantCulture })!;
        }

        return default;
    }
Neos Santos
  • 456
  • 7
  • 8
  • 1
    I ended up using this https://stackoverflow.com/a/23547867/14576266 as a solution for my needs, but what you have proposed here is also helpful. Thanks! – gryz Sep 22 '21 at 10:30