简体   繁体   中英

What is the best way to attach static methods to classes rather than to instances of a class?

If I have a method for calculating the greatest common divisor of two integers as:

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

What would be the best way to attach that to the System.Math class?

Here are the three ways I have come up with:

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

// Lame...

var gcd = a.GCD(b);

and:

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);

and:

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);

The desired syntax is Math.GCD since that is the standard for all mathematical functions.

Any suggestions? What should I do to get the desired syntax?

You cannot. Extension methods are just syntactic sugar for calling a static function and passing an instance of a particular type. Given that, they operate only on instances, as they must be defined by passing a this parameter of the type you want to attach to.

I would prefer the one with RationalMath . You really don't need extension methods here, because their aim is to mimic instance methods of objects of you can't modify. But here one should use plain old static method.

Given the fact that you cannot extend the static Math class I would go for sample #2. It follows the pattern used by Math, does not clutter the int method space, and is simple and clean to invoke. #3 is plain horrible :)

Personally, I wouldn't do it the way you want. System.Math is just one static class that contains some mathematical functions . . . there's no reason it has to contain every mathematical function you'd ever want to use.

However, if you really want this, I suppose you could write your own static Math class that's a sort of wrapper for System.Math . . . basically just implement every function in System.Math by passing it along to the actual System.Math class. Like this:

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.
}

This seems like a real pain in the neck though for not much benefit. (Kind of an anti -syntactic sugar.) But it would let you call Math.GCD(a,b) and, say, Math.Pow(x,y) from the same class, which is what it sounds like you want.

Ok, one other way I thought of:

namespace My
{
    public static class Math
    {
    }
}


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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM