假设我想编写一个类似下面的函数(像往常一样,这是一个简单的例子用于说明目的):
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
正如您可能猜到的,此函数会导致错误,因为无法保证通用对象实现+运算符。据我所知,任何数字类型(整数,双数,十进制等)都会。
有没有办法编写一个(quasi-)泛型函数,可以接受任何数字类型,而不必自己为每个这样的类型显式地重载函数?
或者,我认为同样可接受的解决方案是以某种方式检查类型是否实现'+'运算符(或通常与数字类型相关并由函数使用的任何运算符)。
答案 0 :(得分:8)
不,因为没有特定的通用接口,所有这些接口都会实现。从本质上讲,框架中没有“数字类型”的真实概念。除非你将它们包装在自定义的类中,并且你的方法只接受你的类型(这不是你问题的直接答案,只是一种解决方法)。
答案 1 :(得分:1)
很抱歉,除非您创建自己的号码,否则不能。
public static T Add<T> (T x, T y) where T: MyNumberClass
{
// your add code
...
}
原因是.NET只允许您使用类或接口约束泛型方法。
答案 2 :(得分:1)
您可以使用lambda表达式,如下所示:
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);
}
它不是类型安全的,但它适用于具有预期运算符的类型(在上例中添加)。
答案 3 :(得分: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
这不是你想要的,但公共功能将是类型安全的。
答案 4 :(得分:0)
好消息:现在在 .NET 6 和 C# 10 中有一个解决方案,参见。 https://devblogs.microsoft.com/dotnet/preview-features-in-net-6-generic-math/#generic-math
我目前无法估计此功能是否也可以在 VB.NET 中使用。
为了接受任何数字类型,请使用 INumber<T>
接口,例如:
public T Adding<T>(T a, T b)
where T : INumber<T>
where T : IAdditionOperators<T, T, T>
{
return a + b;
}
注意:在我回答时,此功能只是一个预览。微软将在 .NET 6 的最终版本中保留这一点,因为他们仍然希望允许打破机会。要使用该功能,必须在项目配置中启用预览功能:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<EnablePreviewFeatures>true</EnablePreviewFeatures>
<LangVersion>preview</LangVersion>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Runtime.Experimental" Version="6.0.0-preview.7.21377.19" />
</ItemGroup>
</Project>