6

私はこのような方法を持っています:

private static double ComputePercentage(ushort level, ushort capacity)
{
      double percentage;
      if(capacity == 1)
        percentage = 1;

      // do calculations...
      return percentage;
}

予想されるメソッドのタイプ (または関数に入れられるタイプ) に応じて、10 進数または倍精度のいずれかを返すことができる「タイプ T」のようなジェネリック型にすることは可能ですか?

「1」のような数値をジェネリック型に割り当てることができないため、このようなことを試しましたが、機能しませんでした。後で「where T :」も使用してみましたushort capacity)が、まだわかりませんでした。

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

      // do calculations...
      return percentage;
}

これは可能ですか?確かではありませんでしたが、この投稿は、私がやろうとしていることはまったく不可能であることを示唆しているかもしれないと思いました.


編集

回答者の皆様、多くの良い回答をありがとうございました。Tomasが指摘したように、これはおそらく 2 つの別々の方法で行うのが最適です。TreDubZeddTcKsの両方で指摘されているように、必要な機能を取得するための最良の方法は、double または decimal を暗黙的に返すことができる暗黙的な変換を使用することです。

4

7 に答える 7

5

実際、ジェネリックは必要ありませんが、オーバーロードは必要です。ただし、IL ではサポートされているが C# ではサポートされていない戻り値の型によるオーバーロードが必要です。

私はすべての戻り値の型に対して 2 つのメソッドを好みます。

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

代替手段は、暗黙のキャスト演算子を使用したカスタム型にすることができます。

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;
    }
}
于 2010-05-27T22:55:23.073 に答える
3

暗黙的な変換を使用できる場合があります:http://msdn.microsoft.com/en-us/library/zk2z37d3.aspx

于 2010-05-27T22:27:48.850 に答える
3

ジェネリックは、任意の型で動作するコードを作成するのに役立ちます (おそらく、 を使用して指定できる何らかのインターフェイスを実装しますwhere)。ただし、2 つの異なる数値型を返すことができるメソッドを実装するためにそれらを使用したい場合は、少し間違っているように感じます (何らかの共有インターフェイスdoubleを実装している場合にのみ機能します)。decimal

おそらく、2 つの異なるメソッドを定義する必要があります (たとえばComputePercentage、 andComputePercentagePreciseまたはそのようなもの - 異なるパラメーターを使用してオーバーロードを使用できないため)。

次のようなものを使用して、この制限を回避できる場合があります (ただし、これはおそらく非常に複雑です)。

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> { ... }

次にINumericOps<T>、型パラメーターとして取り、それを使用してメソッド内のすべての数学を行うメソッドを作成します。

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;  
}  

次に、次のように呼び出します。

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

これは素晴らしいトリックであり、おそらく最善の (タイプ セーフな) 回避策です。ただし、少し複雑なので、2 つの別々のメソッドを宣言する方がよいかもしれません。

于 2010-05-27T22:45:48.603 に答える
1

きれいではありませんが、試してみてください。

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

これは、少なくとも両方doubleで機能します。decimal

于 2010-05-27T22:28:34.807 に答える
0

C#4.0を使用している場合は、を返すことができますdynamic

于 2010-05-27T22:34:41.150 に答える
0
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();
}
于 2010-05-27T22:27:55.043 に答える
0

パーセントクラスを作成してみませんか?

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);
}
于 2010-05-27T23:00:21.283 に答える