将静态方法附加到类而不是类的实例的最佳方法是什么?

时间:2010-03-30 12:47:34

标签: c# .net math extension-methods language-features

如果我有一个计算两个整数的最大公约数的方法:

public static int GCD(int a, int b)
{
    return b == 0 ? a : GCD(b, a % b);
}

将它附加到System.Math类的最佳方法是什么?

以下是我提出的三种方式:

public static int GCD(this int a, int b)
{
    return b == 0 ? a : b.GCD(a % b);
}

// Lame...

var gcd = a.GCD(b);

public static class RationalMath
{
    public static int GCD(int a, int b)
    {
        return b == 0 ? a : GCD(b, a % b);
    }
}

// Lame...

var gcd = RationalMath.GCD(a, b);

public static int GCD(this Type math, int a, int b)
{
    return b == 0 ? a : typeof(Math).GCD(b, a % b);
}

// Neat?

var gcd = typeof(Math).GCD(a, b);

所需语法为Math.GCD,因为这是所有数学函数的标准。

有什么建议吗?我该怎么做才能获得所需的语法?

5 个答案:

答案 0 :(得分:11)

你做不到。扩展方法只是用于调用静态函数和传递特定类型实例的语法糖。鉴于此,它们仅在实例上运行,因为它们必须通过传递要附加的类型的this参数来定义。

答案 1 :(得分:6)

我更喜欢RationalMath的那个。你真的不需要这里的扩展方法,因为他们的目的是模仿你无法修改的对象的实例方法。但是这里应该使用普通的静态方法。

答案 2 :(得分:4)

鉴于您无法扩展静态Math类,我会选择样本#2。它遵循Math使用的模式,不会使int方法空间混乱,并且调用简单而干净。 #3非常可怕:)

答案 3 :(得分:3)

就个人而言,我不会按照你想要的方式去做。 System.Math只是一个包含一些数学函数的静态类。 。 。没有理由它必须包含你想要使用的每个数学函数。

但是,如果确实想要这个,我想你可以编写自己的静态Math类,它是System.Math的一种包装器。 。 。基本上只是通过将它传递给实际的System.Math类来实现System.Math中的每个函数。像这样:

public static class Math
{

  public static int GCD(int a, int b)
  {
     return b == 0 ? a : GCD(b, a % b);
  }

  // Implement the System.Math methods
  public static double Pow(double x, double y)
  {
    return System.Math.Pow(x, y);
  }
  // etc.
}

这似乎是一个真正的痛苦,虽然没有太大的好处。 (一种 -syntactic糖。)但它可以让你从同一个班级拨打Math.GCD(a,b),比如Math.Pow(x,y),这听起来像是你想要的

答案 4 :(得分:0)

好的,我想到的另一种方式:

namespace My
{
    public static class Math
    {
    }
}


namespace MainApp
{
    ...
    var gcd = My.Math.GCD(a, b);
    ...
}