1

I have a generic type called TValue. I want to do something like this:


public TValue Number {get;set;}
public TValue GetMaxNumber()
{
   switch (Number)
   {
       case int @int:
           if (@int == default(int))
           {
               return int.MaxValue;
           }
       case long @long:
           //get max value of long
       case short @short:
           //get max value of short
       case float @float:
           //get max value of float
       case double @double:
           //get max value of double
       case decimal @decimal:
           //get max value of decimal
       default:
           throw new InvalidOperationException($"Unsupported type {Number.GetType()}");
    }
}

I want the GetMaxNumber method to return the maximum possible value for that number type. If it is not a number type then throw an exception.

The main issue I have here is that I don't understand how to convert something like an int back to the original generic type, while using int's properties, such as MaxValue.

How do I make this work?

Misha Zaslavsky
  • 8,414
  • 11
  • 70
  • 116
Josh
  • 575
  • 7
  • 17
  • Is this an academic exercise? – Caius Jard Aug 04 '21 at 16:16
  • Nope, it's an actual use case. I need to build a generic blazor input component which can accept any number types (while validating max and min). – Josh Aug 04 '21 at 16:18
  • You can try casting it as dynamic before returning – dogyear Aug 04 '21 at 16:25
  • 1
    Validating max and min is not actually possible when you're dealing with the type itself, though -- as in, comparing an `int` value to `int.MaxValue` will always yield that it's not more than that, by definition. To do this properly you'd need the actual value in a type big enough to do the comparison, or, if the input is going to be string-based, you may as well rely on the `.TryParse`/`Convert` methods to validate it, which covers all the other cases of malformed input a well. – Jeroen Mostert Aug 04 '21 at 16:35
  • Does this answer your question? [Detect MaxValue of generic parameter](https://stackoverflow.com/questions/18180674/detect-maxvalue-of-generic-parameter) and [C# Generics : how to use x.MaxValue / x.MinValue (int, float, double) in a generic class](https://stackoverflow.com/questions/4418636/c-sharp-generics-how-to-use-x-maxvalue-x-minvalue-int-float-double-in-a) and [Get max value from enum using generics](https://stackoverflow.com/questions/56455558/get-max-value-from-enum-using-generics) –  Aug 04 '21 at 16:36
  • From the suggested duplicates, the best approach I think is to use reflection to find the MaxValue method and call it if available. Otherwise to code each case by hand like `case int @int: return (TValue)(object)int.MaxValue;`... –  Aug 04 '21 at 16:39
  • *I need to build a generic blazor input component which can accept any number types* - why not just have the user set the max, then if they have supplied an X they can also supply its X.MaxValue and your component just has a TValue Max property. But also agree with Jeroen; unless youre going to provide a way for a user to set a Max lower than the type's max there aint much point working out the max – Caius Jard Aug 04 '21 at 17:47

3 Answers3

2

If performance is not a big issue and you want to avoid to have a big switch you could do it with reflection (and try / catch)

public TValue GetMaxNumber()
{
    try
    {
        return (TValue)typeof(TValue).GetField("MaxValue").GetValue(null);
    }
    catch
    {
        throw new InvalidOperationException($"Unsupported type {typeof(TValue)}");
    }
}
gsharp
  • 27,557
  • 22
  • 88
  • 134
  • And if performance is a big issue consider caching the results in a dictionary so you only do the reflection part once per type. – russelrillema Sep 27 '22 at 13:05
1

You can convert it this way:

return (TValue)(object)int.MaxValue;

Boxing allows to unbox to the relevant generic type parameter.

Misha Zaslavsky
  • 8,414
  • 11
  • 70
  • 116
-1

Not tested but maybe Convert.ChangeType:

var conversionType = typeof(TValue);
return (TValue)Convert.ChangeType(int.MaxValue, conversionType);
GH DevOps
  • 305
  • 1
  • 11