2009-06-04 4 views
3

私は(例示的な目的のために簡単な例、いつものように)、以下のような機能を書きたいとしよう:数値型のみを受け入れる汎用関数を.NETで記述することはできますか?

Public Function calcSqSum(Of T)(ByVal list As IEnumerable(Of T)) As T 
    Dim sumSq As T 

    For Each item As T In list 
     sumSq += (item * item) 
    Next 

    Return sumSq 
End Function 

あなたはおそらく推測できるとおり、一般的なオブジェクトはに保証されていないので、この関数はエラーが発生+演算子を実装します。私の知る限り、数値型(整数、倍精度、小数点など)があります。

数値タイプを受け入れることができる(準)汎用関数を作成する方法はありますか?そのようなすべての型の関数を明示的にオーバーロードする必要はありませんか?

また、型が '+'演算子(または一般に数値型に関連付けられ、関数で使用される演算子)を実装しているかどうかを何らかの形でチェックすることもできます。

答えて

8

いいえ。すべての機能が実装されている特定の共通インターフェイスがないためです。本質的に、フレームワークには「数値型」という概念はありません。自分で定義したクラスでそれらをラップして、あなたのメソッドがあなたの型だけを受け入れるのでない限り(これはあなたの質問への直接的な答えではなく、単に回避策です)。

+0

自分自身をより良くすることはできませんでした。 –

+0

これは私が疑うところです...これは、クラスが特定の演算子を実装しているかどうかを確認するために、二次的な考え方を達成する方法がないことを意味しますか? –

+0

実行時に特定の演算子*をチェックすることはできますが、コンパイル時の一般制約はチェックできません。 T.operator +が可能な場所はありません。 –

1

あなた自身の番号クラスを作成しないと申し訳ありません。

public static T Add<T> (T x, T y) where T: MyNumberClass 
{ 
// your add code 
... 
} 

なぜなら、.NETでは、クラスまたはインターフェイスを使用して汎用メソッドを制約することしかできないからです。

+0

ああ、番号クラスを作成したくない場合は、汎用メソッド自体の中で常に制約チェックを行うことができます。 "where"構文のようなコンパイル時のエラーはありませんが、実行時の例外が発生します。 –

1

あなたはこのように、ラムダ式を使用することができます。

 static T Add<T>(T a, T b) 
    { 
     // declare the parameters 
     ParameterExpression paramA = Expression.Parameter(typeof(T), "a"), 
      paramB = Expression.Parameter(typeof(T), "b"); 
     // add the parameters together 
     BinaryExpression body = Expression.Add(paramA, paramB); 
     // compile it 
     Func<T, T, T> add = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile(); 
     // call it 
     return add(a, b); 
    } 

それはタイプセーフではありませんが、それは(上記の例ではさらに、)期待されるオペレータを持っているタイプのために動作します。

1

代わりにオーバーロードを使用できます。どちらかあなたがサポートする各数値型の本質的に同一の機能を記述します。

Public Function calcSqSum(ByVal list As IEnumerable(Of Integer)) As Integer 
    Dim sumSq As Integer 
    For Each item As Integer In list 
     sumSq += (item * item) 
    Next 
    Return sumSq 
End Function 

Public Function calcSqSum(ByVal list As IEnumerable(Of Double)) As Double 
    Dim sumSq As Double 
    For Each item As Double In list 
     sumSq += (item * item) 
    Next 
    Return sumSq 
End Function 

etc 

をそれとも、それはそれで多くのコードを持っている場合は、プライベートあなたの総称関数を作成し、過負荷パブリック関数とそれを包む:

Private Function calcSqSum1(Of T)(ByVal list As IEnumerable(Of T)) As T 
    Dim sumSq As T 

    For Each item As T In list 
     sumSq += (item * item) 
    Next 

    Return sumSq 
End Function 

Public Function calcSqSum(ByVal list As IEnumerable(Of Integer)) As Integer 
    Return calcSqSum1(list) 
End Function 

Public Function calcSqSum(ByVal list As IEnumerable(Of Double)) As Double 
    Return calcSqSum1(list) 
End Function 

etc 

これはあなたの後ろにあるものではありませんが、パブリック関数はタイプセーフです。

関連する問題