Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C中模拟Java通用通配符#_Java_C#_Generics_Wildcard - Fatal编程技术网

如何在C中模拟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() {

下面的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()
    {
        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);