0

さまざまな数値タイプを取り、それらを2番目のメソッドのために前処理するメソッドを構築しようとしています。単にオーバーロードするべきなのか、ジェネリックメソッドを使用するべきなのかわかりません。ジェネリックメソッドを使用しようとしましたが、メソッドがパラメータタイプを認識していないようです。コードは以下のとおりです。この場合、オーバーロードするのが良いのか、一般的なメソッドを使用するのが良いのか、誰かに説明してもらえますか?また、これを行うためにジェネリックメソッドを使用したい場合、どうすればそれを機能させることができますか?どうもありがとうございます。

 public static class math
 {
      public static int nextpow2<T>(T a)
      {
           double w;
           if ( a.GetType() is sbyte   ||
                a.GetType() is byte    ||
                a.GetType() is short   ||
                a.GetType() is ushort  ||
                a.GetType() is int     ||
                a.GetType() is uint    ||
                a.GetType() is long    ||
                a.GetType() is ulong   ||
                a.GetType() is float   ||
                a.GetType() is double  ||
                a.GetType() is decimal
           ) w = (double)Convert.ChangeType(a, typeof(double));
           else
                throw new System.ArgumentException("Internal error in nextpow2: argument a is not a number!");

           return _nextpow2(w);
      }

      private static int _nextpow2(double a)
      {
           double index = Math.Abs(a);
           int p = (index > 1) ? (int)Math.Ceiling( Math.Log( index, 2.0) ) : 0;

           return p;
      }

私は次のようにメソッドを呼び出しています:

 int indx = 0;
 int p = math.nextpow2(indx);

コードのコンパイルに失敗します。次のエラーが発生します。

nextpow2の内部エラー:引数aは数値ではありません!

誰かが私が間違っていることを説明できますか?ありがとうございました。

4

2 に答える 2

3

誰かが私が間違っていることを説明できますか?

もちろん。Typeオブジェクトが、、sbyteまたはなどであるかどうかをチェックしています。タイプがなどのタイプを表しbyteているかどうかをチェックしていません...値がであるかどうかを確認しています。それは決してありません。(これが、コンパイル時エラーが発生する理由です。)sbytesbyte

あなたが使用することができます:

if (a.GetType() == typeof(byte) ||
    // etc)

しかし、私はおそらくそうしません。私はこれを一般的なメソッドにはしませ。本当に機能が必要な場合は、次のように記述します。

private static readonly HashSet<Type> ValidTypes = new HashSet<Type>
{
    typeof(sbyte), typeof(byte), /* etc */
};

public static double ConvertToDouble(object x)
{
    if (x == null)
    {
        throw new ArgumentNullException("x");
    }
    if (!ValidTypes.Contains(x.GetType())
    {
        throw new ArgumentException("...");
    }
    return Convert.ChangeType(x, typeof(double));
}

これが1つのことをどのように行っているかに注意してください:引数をに変換しますdouble。それから電話をかけることに意味はありません_nextpow2-発信者が望むならそれをするのは簡単です。

さらに、あなたは2つの矛盾したことを書きました:

コードのコンパイルに失敗します。次のエラーが発生します:
nextpow2の内部エラー:引数aは数値ではありません!

コンパイルに失敗した場合(これは私が期待していることですが)、コードを実行することはできません。つまり、例外を取得することはできません。次のようなコンパイル時エラーを区別する必要があります。

warning CS0184: The given expression is never of the provided ('sbyte') type

および実行時の例外。

また、クラス名とメソッド名の両方が、通常の.NET命名規則に違反しています。

于 2013-03-19T19:08:50.500 に答える
2

あなたはどちらかを言うことができます

a is sbyte

または言う

a.GetType() == typeof(sbyte)

しかし、それをに混ぜても意味がありませんa.GetType() is sbyte。それについてコンパイラの警告が表示されるはずです!Fora.GetType()は、から派生するオブジェクトになりますSystem.Type(実際にはSystem.RuntimeType)。したがって、派生することはできませんsbytesbyte封印されているため、構造体であり、sbyteそれ自体はとからのみ派生しますValueTypeObject

一般的な方法よりも優れた解決策は、次のことです。

public static int Nextpow2(double a)
{
    ...
}

を除くすべての数値型decimalは、暗黙的にに変換可能doubleです。したがって、上記の署名を使用すると、必要に応じて使用できます。

int indx = 0;
int p = math.Nextpow2(indx);
于 2013-03-19T19:14:14.747 に答える