C# 如何使用泛型将两个函数合并为一个函数?

C# 如何使用泛型将两个函数合并为一个函数?,c#,generics,C#,Generics,假设我有以下功能: public int Compute(int a, int b, int c) { return (a + b +c)/3; } public double Compute(double a, double b, double c) { return ((a + b + c) / 3.0) / 209; } 我希望差别是显而易见的。双精度值需要除以209(常量值),而整数不需要除以209 使用泛型将这两个函数组合成一个函数的最佳方法是什么?我不确定这

假设我有以下功能:

public int Compute(int a, int b, int c)
{   
    return (a + b +c)/3;
}

public double Compute(double a, double b, double c)
{
    return ((a + b + c) / 3.0) / 209;
}
我希望差别是显而易见的。双精度值需要除以209(常量值),而整数不需要除以209


使用泛型将这两个函数组合成一个函数的最佳方法是什么?

我不确定这是否有意义。 泛型是避免为不同对象类型编写类似代码的方法


但是在你的例子中,我没有看到任何类似的代码可以通用化,因此保持函数不同可以更好地解决任务。

简短回答

你不能把它变成一个函数

长答案

您唯一的通用代码是:

return (a + b +c)/
您可以使用泛型,最多也可以这样做(使用C#是不可能的):

但你不能这样做,因为或


此外,即使有可能,在这种特定情况下,您也不会获得太多收益,因为在我的假设解决方案中,用法看起来有多么笨拙。

您不应该使用泛型,但您可以测试
a
b
c
是否为
int
s,然后选择您的操作:

private double Compute(double a, double b, double c)
{
    /*         check if a, b and c are integers         int if true          double if false    */
    return (a % 1 == 0 && b % 1 == 0 && c % 1 == 0) ? (a + b + c) / 3 : ((a + b + c) / 3.0) / 209;
}

[TestMethod()]
public void Int()
{
    int a = 1;
    int b = 2;
    int c = 3;
    int result = (int)Compute(a, b, c);

    int expected = (1 + 2 + 3) / 3;

    Assert.AreEqual(expected, result);
}

[TestMethod()]
public void Double()
{
    double a = 1.1;
    double b = 2.2;
    double c = 3.3;
    double result = Compute(a, b, c);

    double expected = ((1.1 + 2.2 + 3.3) / 3.0) / 209;

    Assert.AreEqual(expected, result);
}

两次考试都通过了,我有个主意。我可以创建一个泛型方法,它为每种情况
int
double
接收一个
Delegate
。这个版本的小提琴很管用

publicstaticvoidmain()
{   
Func x=(d1,d2,d3)=>{return((d1+d2+d3)/3.0)/209;};
Func y=(i1,i2,i3)=>{return(i1+i2+i3)/3;};
var rsDouble=计算(1.0,2.0,3.0,x);
控制台写入线(rsDouble);
var rsInt=计算(1,2,3,y);
控制台写入线(rsInt);
}
公共静态T计算(T a、T b、T c、Func动作)
{
返回动作(a、b、c);
}

但这似乎使情况变得复杂,我同意其他答案,泛型用于为不同的对象类型编写类似的代码,而不是为每个参数编写不同的代码。

泛型用于使操作…嗯…泛型。依我看,它们用于使操作不关心它们所操作的类型。你的操作显然很重要,因为它的行为是不同的。我认为最好的方法是根本不做&保持现状,是否有理由要求使用通用版本?如果你这样做,代码会更干净…签名可以变得通用:public T Compute(ta,tb,tc)。但是,由于使用double和int执行的操作不同,因此必须检查泛型方法中的类型,这意味着它首先不应该是泛型的。此外,并非所有类型都支持数学运算,因此它在大多数非数字类型上都会失败。即使使用
(a+b+c)/3
将零件提取到共享的泛型方法中也不实用,因为c无法将泛型类型参数约束为允许
+
//code>等操作的“算术”参数。如果这是你真正想问的,那是不可能的。对,但如何将它推广到其他类型,比如long?有什么规则吗?没有。只有整数类型和实数类型是可以区分的。那就没有我之前写的意义了。你只会让逻辑更难理解。@anonymous非数字结构呢?@RufusL,它们被排除在外。这样做毫无意义:为什么有人会将
int
传递给一个签名要求
双精度的方法?当然,这是可行的,但这是黑客比其他任何东西。作为一名优秀的程序员,您需要针对接口(签名)而不是方法的实现进行编程。
Compute(1, 2, 3, 3, 1); // For integers
Compute(1.0, 2.0, 6.0, 3.0, 209); // For doubles
private double Compute(double a, double b, double c)
{
    /*         check if a, b and c are integers         int if true          double if false    */
    return (a % 1 == 0 && b % 1 == 0 && c % 1 == 0) ? (a + b + c) / 3 : ((a + b + c) / 3.0) / 209;
}

[TestMethod()]
public void Int()
{
    int a = 1;
    int b = 2;
    int c = 3;
    int result = (int)Compute(a, b, c);

    int expected = (1 + 2 + 3) / 3;

    Assert.AreEqual(expected, result);
}

[TestMethod()]
public void Double()
{
    double a = 1.1;
    double b = 2.2;
    double c = 3.3;
    double result = Compute(a, b, c);

    double expected = ((1.1 + 2.2 + 3.3) / 3.0) / 209;

    Assert.AreEqual(expected, result);
}
    public static void Main()
    {   
        Func<double,double,double,double> x = (d1,d2,d3) => {return ((d1 +d2 + d3)/ 3.0) / 209;};

        Func<int,int,int,int> y = (i1,i2,i3) => {return (i1 + i2 + i3)/ 3;};

        var rsDouble = Compute<double>(1.0,2.0,3.0,x);
        Console.WriteLine(rsDouble);

        var rsInt = Compute<int>(1,2,3,y);
        Console.WriteLine(rsInt);

    }

    public static T Compute<T>(T a, T b, T c, Func<T,T,T,T> action)
    {
        return action(a,b,c);
    }