【问题标题】:What is the best way to attach static methods to classes rather than to instances of a class?将静态方法附加到类而不是类的实例的最佳方法是什么?
【发布时间】:2010-03-30 12:47:33
【问题描述】:

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

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,因为这是所有数学函数的标准。

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

【问题讨论】:

  • 您的代码也适用于var gcd = typeof(string).GCD(a, b) - 它只需要一个Type 的实例...我认为您想要做的实际上是不可能的。
  • 很明显,是的。但我希望人们明白 GCD 函数只是另一个数学函数。
  • 恕我直言,你能做的最好的就是在 MoreMath 类或类似类中定义 GCD
  • @Adam 是对的。这是不可能的。如果没有 Math 的源代码并重建包含它的程序集,则无法向 Math 类添加静态方法。

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


【解决方案1】:

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

【讨论】:

  • @Nick:你可以直接调用任何扩展方法。你的意思是什么?
  • 那么,我如何获得我想要的语法?这是手头的问题,不一定直接使用扩展方法......现在,这个答案没有帮助。我已经完全意识到扩展方法不能应用于类本身...
  • @John:同样,您所要求的对于任何版本的 C#(或任何其他 .NET 语言)都是不可能的。除了“你不能”之外,您的问题没有其他答案。
  • @John:我们在绕圈子。你想要的语法是System.Math.GCD。我说这是不可能的。你说你知道。我问你为什么问这个问题。你说要得到你知道的语法是不可能的。 ??? = 利润。
  • @John,你有点难!您不能扩展 System.Math。您已经知道您的选择:int 上的扩展方法,或者您自己的静态(任何)Math 类。而且,正如亚当指出的那样,如果您选择 My.Math,那么您必须在需要时完全限定 System.Math。就个人而言,我会选择一个名为 MathUtility 的静态数学实用程序类。
【解决方案2】:

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

【讨论】:

  • 我将其命名为 Math。如果真的需要,您可以为所有 Math 函数编写包装器,然后告诉所有开发人员只使用 Math ...但这可能有点矫枉过正。
  • @TheSean:我刚刚也将其发布为答案。 . .虽然我同意这可能不值得。
【解决方案3】:

鉴于您无法扩展静态 Math 类,我将选择示例 #2。它遵循 Math 使用的模式,不会弄乱int 方法空间,并且调用起来简单干净。 #3 太可怕了:)

【讨论】:

  • 我知道是的。这就是我在这里的原因。 :)
【解决方案4】:

就我个人而言,我不会按照你想要的方式去做。 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.
}

这似乎是一种真正的颈部疼痛,尽管没有多大好处。 (有点像 句法糖。)但它会让你在同一个类中调用 Math.GCD(a,b),比如说,Math.Pow(x,y),这听起来像你想要的。

【讨论】:

  • 欢迎提出真正的建议!我同意这是矫枉过正。
【解决方案5】:

好的,我想到了另一种方法:

namespace My
{
    public static class Math
    {
    }
}


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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-10
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    相关资源
    最近更新 更多