How to create a generic C # method that can return either double or decimal?

I have a way like this:

private static double ComputePercentage(ushort level, ushort capacity) { double percentage; if(capacity == 1) percentage = 1; // do calculations... return percentage; } 

Is it possible to make it a type of a general type like “T”, where it can return either decimal or double, depending on the type of expected method (or the type introduced into the function?)

I tried something like this, and I could not get it to work, because I cannot assign a number like "1" to the general type. I also tried using "where T:" after ushort capacity) , but I still could not understand.

 private static T ComputePercentage<T>(ushort level, ushort capacity) { T percentage; if(capacity == 1) percentage = 1; // error here // do calculations... return percentage; } 

Is it possible? I was not sure, but I thought this post might seem like what I'm trying to do is simply impossible.


EDIT

Thanks to everyone who answered, many good answers. As Tomas noted, this is probably best done in two different ways. As both TreDubZedd and TcKs pointed out , the best way to get the functionality that I would like to use is to use an implicit conversion that can return double or decimal implicitly.

+6
generics c # implicit
source share
7 answers

In fact, you do not need generics, but overload. However, you need overloading by return type, which is supported by IL but not supported by C #.

I prefer two methods for each return type:

 static double ComputePercentageDouble (ushort level, ushort capacity) static decimal ComputePercentageDecimal (ushort level, ushort capacity) 

An alternative could be the custome type with implicit operators:

 decimal decimalPercentage = ComputePercentage( 1, 2 ); double doublePercentage = ComputePercentage( 1, 2 ); static DoubleDecimal ComputePercentage( ushort level, ushort capacity ) { DoubleDecimal percentage = default( DoubleDecimal ); if ( capacity == 1 ) percentage.Number = 1; // error here // do calculations... return percentage; } public struct DoubleDecimal { public decimal Number; public static implicit operator decimal( DoubleDecimal value ) { return value.Number; } public static implicit operator double( DoubleDecimal value ) { return (double)value.Number; } } 
+5
source share

Perhaps you can use the implicit conversion: http://msdn.microsoft.com/en-us/library/zk2z37d3.aspx

+3
source share

Generics are useful for writing code that works with any type (possibly using some interface that can be specified using where ). However, if you want to use them to implement a method that can return two different numeric types, it feels a little wrong (it will only work if double and decimal have some common interfaces implemented).

You should probably define two different methods (e.g. ComputePercentage and ComputePercentagePrecise or something similar - since you cannot use overload using different parameters).

It may be possible to get around this limitation using something like this (but this is probably too complicated for you):

 class INumericOps<T> { public abstract T One { get; } public abstract T Add(T a, T b); // and other operations that you may need } // Implementations of numeric operations for decimal and double class DecimalNumerics : INumericOps<decimal> { ... } class DoubleNumerics : INumericOps<double> { ... } 

Then you should write a method that takes INumericOps<T> as a type parameter and uses it to do all the math inside the method:

 private static R ComputePercentage<T, R>(ushort level, ushort capacity) where T : INumericOps<R>, where T : new() { INumericOps<R> ops = new T(); // Get instance with numeric operations T percentage; if(capacity == 1) percentage = ops.One; // Calculations using ops.Add(.., ..) instead of + etc. return percentage; } 

Then you would call it like this:

 decimal res = ComputePercentage<DecimalNumerics, decimal>(...); 

This is a good trick, and it is probably the best (safe type) workaround you can get. However, this is a bit complicated, so declaring two separate methods might be a better idea.

+3
source share

This is not very, but try:

 percentage = (T)Convert.ChangeType(1, typeof(T)); 

This works for both double and decimal at least.

+1
source share
 private static T ComputePercentage<T>(ushort level, ushort capacity) { if (typeof(T) == typeof(decimal)) { decimal percentage = 1; return (T) (object) percentage; } if (typeof(T) == typeof(double)) { double percentage = 1; return (T) (object) percentage; } throw new NotSupportedExcpetion(); } 
0
source share

If you are using C # 4.0, you can simply return dynamic .

0
source share

Why not create a Percent class?

 class Percent { public Percent(double value) { this.value = value; } public double AsDouble() { return value; } public decimal AsDecimal() { return (decimal)value; } readonly double value; } static Percent ComputePercentage(ushort level, ushort capacity) { double percentage = 0; if (capacity == 1) { percentage = 1; } // calculations return new Percent(percentage); } 
0
source share

All Articles