所以我想使用多态来进行算术运算。
因此,我的第一个念头是为使用算术,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是类类型
答案 0 :(得分:0)
您还为时过早))。 Type Classes
(link)中有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));
}
}
通过实现从T
到Num<T>
的显式强制转换和从Num<T>
到T
的隐式强制转换,这是相当合理的。
如果您确实获得了出色的性能,则可以考虑将包装器类设置为struct
(有时也可以删除readonly
),并在包装器类中的任何地方使用[MethodImpl(MethodImplOptions.AggressiveInlining)]
。