如何在C中模拟Java通用通配符#
下面的Java代码比较两个数组的平均值,一个是整数,一个是双精度数组如何在C中模拟Java通用通配符#,java,c#,generics,wildcard,Java,C#,Generics,Wildcard,下面的Java代码比较两个数组的平均值,一个是整数,一个是双精度数组 class Generic_Class<T extends Number> { T[] nums; // array of Number or subclass Generic_Class(T[] o) { nums = o; } // Return type double in all cases. double average() {
class Generic_Class<T extends Number>
{
T[] nums; // array of Number or subclass
Generic_Class(T[] o)
{
nums = o;
}
// Return type double in all cases.
double average()
{
double sum = 0.0;
for(int i=0; i < nums.length; i++)
sum += nums[i].doubleValue();
return sum / nums.length;
}
// boolean sameAvg(Generic_Class<T> ob)
// Using Generic_Class<T> i get the error:
// incompatible types: Generic_Class<Double> cannot be converted to Generic_Class<Integer>
// Using wilcards I get no error
boolean sameAvg(Generic_Class<?> ob)
{
if(average() == ob.average())
return true;
return false;
}
}
我在C#中也尝试过这样做,但是,因为我没有通配符,所以无法完成相同的任务
我怎样才能用C#做同样的事情
谢谢。只需添加简单的界面,使用方法
双倍平均值
,即可:
interface IAbleToGetAverage
{
double Average();
}
class GenericClass<T> : IAbleToGetAverage
where T : struct, IConvertible
{
private readonly T[] nums; // array of Number or subclass
public GenericClass(T[] o)
{
nums = o;
}
private readonly IFormatProvider formatProvider = new NumberFormatInfo();
public double Average()
{
var sum = 0.0;
for(var i=0; i < nums.Length; i++)
sum += nums[i].ToDouble(formatProvider);
return sum / nums.Length;
}
public bool SameAvg(IAbleToGetAverage ob)
{
if(Math.Abs(Average() - ob.Average()) < double.Epsilon)
return true;
return false;
}
}
接口IAbleToGetAverage
{
双倍平均数();
}
类GenericClass:IAbleToGetAverage
其中T:struct,IConvertible
{
私有只读T[]nums;//数字或子类的数组
公共泛型类(T[]o)
{
nums=o;
}
private readonly IFormatProvider formatProvider=新的NumberFormatInfo();
公众双倍平均
{
var总和=0.0;
对于(变量i=0;i
您在Java代码中表达的是装箱数字类型,它们都扩展了Number
类,因此强制执行泛型类型为数字的约束是很简单的
类型在C中的工作方式略有不同,因为int
而不是与Java相同意义上的原语,只是System.Int32
的类型别名,后者是struct
此外,C#中没有只由数字共享的公共基类型(类、结构、接口等),因此不可能创建约束来强制泛型类型为数字,具有数值,因此可以对其执行数学计算
这里的一些建议似乎是使用
where T:I可比较,struct
,但我可以说,该约束也适用于DateTime
,Guid
和TimeSpan
——它们都不是整数或浮点数。正如其他回答者所说,在C#中没有与数字等价的词。您所能得到的最好结果是struct,IConvertible
。但是,还有另一种方法来执行通用通配符
只需使用另一个通用参数:
public class Generic_Class<T> where T : struct, IConvertible
{
T[] nums;
public Generic_Class(T[] o)
{
nums = o;
}
public double Average()
{
double sum = 0.0;
for(int i=0; i < nums.Length; i++)
sum += nums[i].ToDouble(null);
return sum / nums.Length;
}
// this is the important bit
public bool SameAvg<U>(Generic_Class<U> ob) where U : struct, IConvertible
{
if(Average() == ob.Average())
return true;
return false;
}
}
公共类泛型\u类,其中T:struct,IConvertible
{
T[]nums;
公共通用类(T[]o)
{
nums=o;
}
公众双倍平均
{
双和=0.0;
对于(int i=0;i
计算一系列数字的平均值内置于C#:
areEqual==true
运行上述操作后
您甚至可以使用Average
重载对复杂类型执行此操作,该重载使用Func
返回值:
public class MyValue
{
private static Random rnd = new Random();
public int SomeInt { get; set; } = rnd.Next();
}
var myObjArray = new MyValue[] { new MyValue(), new MyValue(), new MyValue(), new MyValue() };
var myAvg = myObjArray.Average(o => o.SomeInt);
所以不,通配符在C#中不可用,但在这种情况下,使用泛型可以通过使用Func
的多个重载来模拟通配符
请参见这看起来不像c。是Java吗?@ZoharPeled,是的,是Java。几秒钟前我编辑了代码。我编辑了您的标题并添加了java标记以使您的问题更清楚。您没有显示您的C#代码,也没有具体说明它是如何工作的。
sameAvg
代码可以简化为return average()==ob.average()代码>和。。。我可以问一下,您如何让.net framework int和double数组实现该接口?@ZoharPeled…快告诉我!XD@ZoharPeled他们不需要。他们只需要自己的Generic\u类来实现它IAbleToGetAverage@series0ne仅供参考,Guid
和TimeSpan
不是IConvertible
。似乎不可能possible@gabba如果你这么认为,那么就贴出一个实际完成的答案。考虑到你发布了一个不起作用的答案,它并不支持你所说的这是可能的。如果可能的话,你为什么不发布一个真正能做到这一点的答案呢?@serieone,Servy-IConvertible-not-IComparable。IConvertible必须加倍,所以任何IConvertible类型都应该正确实现它!喜欢!说得好!更改实现要比试图插入当时语言中不存在的特性要好!PS有一种用C#表示通配符的方法。。。但据我记忆所及,只有typeof表达式typeof(Generic)
,但我认为这没有用here@series0ne这实际上不像Java那样是一个“通配符”,它是一个带有单个类型参数的泛型类型引用。它只能计算为一个泛型类型,而不能计算为一个实现。我知道,我今天不在表单上。IIRC它基本上只获取泛型类型的System.Type实例,而不指定GTP。是的,它不像Java中的通配符。我也在想同样的事情,并在这里实现了一个小提琴,我50分钟前也在想同样的事情;)详细说明:Java版本是这方面的简写,因为通配符隐式地包含类型参数边界Generic\U Class
相当于Generic\U Class我已将where U:struct,IConvertible更改为where U:IConvertible并起作用。为什么我们需要使用struct约束?@user9559069,因为c#没有与Number
等价的值。我们最接近这一点的是将U
约束为IConvertible
的结构和实现者。
public class Generic_Class<T> where T : struct, IConvertible
{
T[] nums;
public Generic_Class(T[] o)
{
nums = o;
}
public double Average()
{
double sum = 0.0;
for(int i=0; i < nums.Length; i++)
sum += nums[i].ToDouble(null);
return sum / nums.Length;
}
// this is the important bit
public bool SameAvg<U>(Generic_Class<U> ob) where U : struct, IConvertible
{
if(Average() == ob.Average())
return true;
return false;
}
}
var iNums = new int[] { 1, 2, 3, 4, 5 };
var dNums = new double[] { 1.0, 2.0, 3.0, 4.0, 5.0 };
var iAvg = iNums.Average();
var dAvg = dNums.Average();
var areEqual = iAvg == dAvg;
public class MyValue
{
private static Random rnd = new Random();
public int SomeInt { get; set; } = rnd.Next();
}
var myObjArray = new MyValue[] { new MyValue(), new MyValue(), new MyValue(), new MyValue() };
var myAvg = myObjArray.Average(o => o.SomeInt);