这是实现多态以使用算术的好方法吗?

时间:2019-06-06 15:41:58

标签: c# abstract-class

所以我想使用多态来进行算术运算。

因此,我的第一个念头是为使用算术,IAddable等接口。但是我在互联网上发现这是不可能的。但是我想到了一个窍门,现在我很想知道:这是多态性的一种很好且快速的实现吗?

    public abstract class RingElement
    {
        public static RingElement operator +(RingElement e1, RingElement e2)
        {
            if (e1 == null)
                return e2;
            if (e2 == null)
                return e1;
            Type type = e1.GetType();
            return (RingElement) type.GetMethod("op_Addition").Invoke(null, new object[] {e1, e2 });
        }

        public static RingElement operator *(RingElement e1, RingElement e2)
        {
            if (e1 == null)
                return e2;
            if (e2 == null)
                return e1;
            Type type = e1.GetType();
            return (RingElement) type.GetMethod("op_Multiply").Invoke(null, new object[] { e1, e2 });
        }
    }

我制作了两个RingElement:一个doubleElement(只包含一个double)和一个通用 Matrix<T> : RingElement where T : RingElement 空处理是为了实现空总和或空积的可能性。

RingElement的每个继承的类都应具有两个静态方法 public static T operator +(T x, T y) public static T operator *(T x, T y)

具有自己的实现主体,其中T是类类型

2 个答案:

答案 0 :(得分:0)

您还为时过早))。 Type Classeslink)中有c# 9个候选者,可能是c#中最优雅的解决方案。

(如果使用f#是选项,它已经有Statically Resolved Type Parameters,并且此链接下的页面正好显示了用于算法的多态示例)

答案 1 :(得分:0)

这将起作用,使用反射的位可以解决问题。它不是类型安全的,可能不是最有效的方式,但是不幸的是,对于C#中的问题,还没有一个完全令人满意的答案。

以下是一些您可能会觉得有用的建议:

要解决Scott Hannen的有效顾虑,即能够在DogRingElement : RingElement上添加CatRingElement : RingElement,您可以使用奇怪的重复模式,

public abstract class RingElement<T> where T : RingElement<T> { .. }

public class DogRingElement : RingElement<DogRingElement> { .. }
public class CatRingElement : RingElement<CatRingElement> { .. }

为了对性能有所帮助,您可以尝试

public static RingElement operator +(RingElement e1, RingElement e2)
{
    return (RingElement) ((dynamic) e1 + (dynamic) e2);
}

一开始它的性能受到较大影响,但在首次使用后会变得更快。

您可以在Matrix实现中使用dynamic变量,

class Matrix<T>
{
     public static Matrix<T> operator + (Matrix<T> a, Matrix<T> b)
     {
         // check a.M = b.M, a.N = b.N
         var c = new Matrix<T>(a.M, a.N);
         for (var i = 0; i < a.N ; i ++)
         {
             for (var i = 0; i < a.N ; i ++)
             {
                  dynamic x = a[i, j], y = b[i, j];
                  c[i,j] = (T) (x + y);
             }
         }
         return c;
    }
}

该性能第一次使用时效果并不理想,但随后下降。

您还可以考虑一个实现算术运算符的包装器类,其中包含对使用Add,Mult等方法实现接口的对象的引用。

public interface IRingElem<T>   // strangely recurring pattern
     where T : IRingElem<T>
{
    T Add(T);
}

public class Num<T>
     where T : IRingElem<T>
{
    private readonly T elem;

    public static Num<T> operator + (Num<T> a, Num<T> b)
    {
        return new Num<T>(a.elem.Add(b.elem));
    }

}

通过实现从TNum<T>的显式强制转换和从Num<T>T的隐式强制转换,这是相当合理的。

如果您确实获得了出色的性能,则可以考虑将包装器类设置为struct(有时也可以删除readonly),并在包装​​器类中的任何地方使用[MethodImpl(MethodImplOptions.AggressiveInlining)]

>