实现算术仿制药?算术

2023-09-02 10:51:44 作者:曾经沧海难为水

是否有可能在C#泛型实现基本运算(至少加),就像你可以的 C ++模板?我一直在尝试了一段时间,让他们和工作,但C#不会让你声明相同的一般类型多次,比如你可以用模板。

Is it possible to implement basic arithmetic (at least addition) in C# generics, like you can with C++ templates? I've been trying for a while to get them up and working, but C# doesn't let you declare the same generic type multiple times, like you can with templates.

广泛的谷歌搜索并没有提供答案。

Extensive googling did not provide an answer.

编辑:谢谢你,但我正在寻找一个方式做算术在编译时,嵌入像在泛型类型Church数。这就是为什么我联系,我做了文章。算术的在的泛型类型,而不是算术的的实例的泛型类型。

Thanks, but what I'm looking for is a way to do the arithmetic at compile time, embedding something like Church numerals in generics types. That's why I linked the article that I did. Arithmetic in generic types, not arithmetic on instances of generic types.

推荐答案

不幸的是你不能使用泛型类型的算术运算

Unfortunately you cannot use arithmetic operations on generic types

T Add(T a, T b)
{
    return a + b; // compiler error here
}

不会在C#中的工作!

will not work in c#!

但你可以创建自己的数字类型和重载运算符(算术平等和明确)。这使您可以与他们在一个很自然的方式工作。但是你不能创建泛型继承层次。你将不得不使用非通用基类或接口。

But you can create your own numeric types and overload the operators (arithmetic equality and implicit, explicit). This lets you work with them in a quite natural way. However you cannot create an inheritance hierarchy with generics. You will have to use a non generic base class or interface.

我只是做了一个向量类型。这里的一个缩短的版本:

I just did it with a vector type. A shortened version here:

public class Vector
{
    private const double Eps = 1e-7;

    public Vector(double x, double y)
    {
        _x = x;
        _y = y;
    }

    private double _x;
    public double X
    {
        get { return _x; }
    }

    private double _y;
    public double Y
    {
        get { return _y; }
    }

    public static Vector operator +(Vector a, Vector b)
    {
        return new Vector(a._x + b._x, a._y + b._y);
    }

    public static Vector operator *(double d, Vector v)
    {
        return new Vector(d * v._x, d * v._y);
    }

    public static bool operator ==(Vector a, Vector b)
    {
        if (ReferenceEquals(a, null)) {
            return ReferenceEquals(b, null);
        }
        if (ReferenceEquals(b, null)) {
            return false;
        }
        return Math.Abs(a._x - b._x) < Eps && Math.Abs(a._y - b._y) < Eps;
    }

    public static bool operator !=(Vector a, Vector b)
    {
        return !(a == b);
    }

    public static implicit operator Vector(double[] point)
    {
        return new Vector(point[0], point[1]);
    }

    public static implicit operator Vector(PointF point)
    {
        return new Vector(point.X, point.Y);
    }

    public override int GetHashCode()
    {
        return _x.GetHashCode() ^ _y.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        var other = obj as Vector;
        return other != null && Math.Abs(other._x - _x) < Eps && Math.Abs(other._y - _y) < Eps;
    }

    public override string ToString()
    {
        return String.Format("Vector({0:0.0000}, {1:0.0000})", _x, _y);
    }
}