在VB.NET中,如果我想为不同类型的数值变量(Integer
,Long
,Decimal
,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
现在只进行一次操作就可以了,但是我想创建的方法越多,我所做的就越多。
有通用的方法吗?我很想看到这样的东西(伪代码):
<Extension()> _
Public Function Add(Of T As Numeric)(a As T, b As T) As T
Return a + b
End Function
或者还有其他概念吗?
答案 0 :(得分:2)
无法执行此操作,因为您无法将通用类型约束为一组数字类型(Integer
,Long
,Decimal
,Double
)。问题是没有IArithmetic
接口可以用来约束T
,因此你不能这样写:
' This does not work because IArithmetic does not exist
<Extension()> _
Public Function Add(Of T As IArithmetic)(a As T, b As T) As T
Return a + b
End Function
但是,你可以加入这个原因来说服微软通过Microsoft Feedback Center来实现这一点,并提出和/或评论类似的请求。
答案 1 :(得分:1)
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模板生成方法解决这个问题有很好的答案。 Is there a constraint that restricts my generic method to numeric types?
答案 2 :(得分: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等。我使用了double,因为这似乎包含了大部分内容,如果不是所有其他数字类型。当然,这很容易改变。
只需将返回值转换为您需要的任何类型。如果你打开了所有选项,Inellisense会抓住这个并提示你正确的施法
Dim a As String = "5.0"
Dim b As Double = CDbl(a.Add(2))
我知道这会冒犯一些敏感性,但就像我说的那样对一些人来说可能是有用的,作为权宜之计。
这是一个有趣的article。它是用C#编写的,但您可能会发现这些概念也很有用。
答案 3 :(得分:0)
受this answer的启发,以下似乎有效:
<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%,因为您仍然可以在Byte
和Date
上调用此内容,这是不可取的。)
示例:
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)))
有两种泛型类型也允许使用混合数字类型:
<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))
我知道这仍然不理想,因为转换为十进制或返回时可能会有一些损失。如果你不使用小数,这仍然需要转换函数的结果。但它在许多情况下确实避免了重复的需要。