2

IntegerVB.NET では、異なる型 ( 、LongDecimal、 )の数値変数の拡張メソッドが必要な場合Double、これらに対して常に複数のメソッドを定義する必要があります。

<Extension()> Public Function Add(a As Integer, b As Integer) As Integer
    Return a + b
End Function

<Extension()> Public Function Add(a As Long, b As Long) As Long
    Return a + b
End Function

<Extension()> Public Function Add(a As Double, b As Double) As Double
    Return a + b
End Function

<Extension()> Public Function Add(a As Decimal, b As Decimal) As Decimal
    Return a + b
End Function

1 つの操作についてはこれで問題ありませんが、作成したいメソッドが多ければ多いほど、複製を行う必要があります。

そうするための一般的な方法はありますか?私はこのようなものを見たいと思っています (疑似コード):

<Extension()> _
Public Function Add(Of T As Numeric)(a As T, b As T) As T
    Return a + b
End Function

または、そうするための他の概念はありますか?

4

4 に答える 4

1

Jon Skeet はGeneric Operatorsの Operator<T> でこれを解決しました

public static class Operator
{
   public static T And<T>(T value1, T value2)
   {
      return Operator<T>.And(value1, value2);
   }
}

public static class Operator<T>
{
   public static Func<T, T, T> And { get { return and; } }
   static Operator()
   {
      add = ExpressionUtil.CreateExpression<T, T, T>(Expression.Add);
   }
}

@Jeroen Vannevel は、T4 テンプレートを使用してジェネレーター メソッドを使用してこれを解決する方法について優れた回答を提供しています。 ジェネリック メソッドを数値型に制限する制約はありますか?

于 2014-09-18T17:22:53.180 に答える
0

この回答に触発されて、次のことがうまくいくようです:

<Extension()> _
Public Function Add(Of T As {IConvertible, IComparable, IComparable(Of T), 
                             IFormattable, IEquatable(Of T)}) _
                   (a As T, b As T) As Decimal
    Return a.ToDecimal(Nothing) + b.ToDecimal(Nothing)
End Function

型定義は、数値型に近い拡張メソッドを制限します。(ただし、100% ではありません。まだこれを呼び出すことができますがByteDateこれは望ましくありません。)

例:

Dim dec As Decimal = Add(CDec(12.34), CDec(34.56))
Dim sng As Single = CSng(Add(CSng(34.56), CSng(45.67)))
Dim dbl As Double = CDbl(Add(CDbl(123.34), CDbl(45.123)))
Dim int As Integer = CInt(Add(CInt(12), CInt(34)))
Dim lng As Long = CLng(Add(CLng(1200), CLng(3400)))

2 つのジェネリック型を使用すると、混合数値型を使用することもできます。

<Extension()> _
Public Function Add(Of T As {IConvertible, IComparable, IComparable(Of T), 
                             IFormattable, IEquatable(Of T)},
                       U As {IConvertible, IComparable, IComparable(Of U), 
                             IFormattable, IEquatable(Of U)}) _
                   (a As T, b As U) As Decimal
    Return a.ToDecimal(Nothing) + b.ToDecimal(Nothing)
End Function

例:

Dim mixed As Decimal = Add(CDec(12.34), CSng(23.45))

10 進数に変換したり元に戻したりするときに損失が発生する可能性があるため、これはまだ理想的ではないことはわかっています。また、小数を使用していない場合は、関数の結果をキャストする必要があります。ただし、多くの場合、重複する必要はありません。

于 2013-08-08T07:40:53.883 に答える
0

これはまさにあなたが探しているものではありませんが、当面の間、多くの入力を節約するのに役立つ場合があります。

Imports WindowsApplication2.Extensions

Public Module Extensions
    <Extension()>
    Public Function Add(A As Object, B As Object) As Object
        Dim numa, numb As Double
        Dim gooda As Boolean = Double.TryParse(A.ToString, numa)
        Dim goodb As Boolean = Double.TryParse(B.ToString, numb)
        Return numa + numb
    End Function
End Module

より強力なエラー チェックが必要な場合に備えて、2 つのブール値を宣言しました。double に解析できない文字列にキャストされたオブジェクトはすべて 0 として扱われます。この方法でも、string、int、double、long、float などを混在させることができます。他のすべての数値タイプ。もちろん、これは簡単に変更できます。

return を必要な型にキャストするだけです。すべてのオプションがオンになっている場合、Inellisense はこれをキャッチし、適切なキャストを求めるプロンプトを表示します。

    Dim a As String = "5.0"
    Dim b As Double = CDbl(a.Add(2)) 

これが一部の感性を怒らせることはわかっていますが、前述したように、応急処置として、一部の人にとっては役立つかもしれません.

ここに興味深い記事があります。これは C# を使用して記述されていますが、概念も役立つ場合があります。

于 2013-08-07T23:27:34.510 に答える