Каков наилучший способ присоединения статических методов к классам, а не к экземплярам класса? - PullRequest
3 голосов
/ 30 марта 2010

Если у меня есть метод для вычисления наибольшего общего делителя двух целых чисел, как:

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 ]

11 голосов
/ 30 марта 2010

Вы не можете. Методы расширения являются просто синтаксическим сахаром для вызова статической функции и передачи экземпляра определенного типа. Учитывая это, они работают только с экземплярами, так как они должны быть определены путем передачи параметра this типа, к которому вы хотите присоединиться.

6 голосов
/ 30 марта 2010

Я бы предпочел тот, с RationalMath. Здесь вам действительно не нужны методы расширения, потому что их цель - имитировать методы экземпляров объектов, которые вы не можете изменять Но здесь следует использовать простой старый статический метод.

4 голосов
/ 30 марта 2010

Учитывая тот факт, что вы не можете расширить статический класс Math, я бы пошел для образца # 2. Он следует шаблону, используемому Math, не загромождает пространство метода int и прост и чист для вызова. # 3 просто ужасно :) 1003 *

3 голосов
/ 30 марта 2010

Лично я бы не поступил так, как ты хочешь. 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) из того же класса, что и звучит так, как вы хотите.

0 голосов
/ 30 марта 2010

Хорошо, еще один способ, которым я подумал:

namespace My
{
    public static class Math
    {
    }
}


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