- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
(我写的是关于矩阵的,但别担心,这不是一道数学题,假设你没有数学知识。)
我有一个包含三个字段的 Matrix
类
double[] Data;
int Rows;
int Columns;
并定义了数百种数学运算。
另外,我有一个 SymmetricMatrix : Matrix
子类,它没有自己的实例字段,它通过继承提供上述所有操作,提供一些额外的操作(如 EigenvalueDecomposition),最后 使用new
关键字重复一些 定义以将返回类型更改为SymmetricMatrix
。
例如,如果 Matrix
有
public Matrix MatrixMultiplication(Matrix otherMatrix)
public Matrix ScaledBy(double scalar)
然后 SymmetricMatrix
将简单地继承 MatrixMultiplication
但它会更改 ScaledBy
以返回 SymmetricMatrix
。
我没有重新实现 ScaledBy
,而是通过
// SymmetricMatrix.cs
public new SymmetricMatrix ScaledBy(double scalar) => base.ScaledBy(scalar).AsSymmetricMatrix()
// Matrix.cs
public SymmetricMatrix AsSymmetricMatrix() => Unsafe.As<SymmetricMatrix>()
(我使用 new
而不是 virtual+override
的原因与这个问题的目的无关紧要)。
我发现这种方法的效果出奇地好,它使我能够非常简洁地定义 SymmetricMatrix.cs
。明显的缺点是它可能会利用不受支持的行为(?)并且它会混淆我经常使用的调试器(转换结果的运行时类型是 Matrix
这不是它的编译时类型 SymmetricMatrix
,然而,在 SymmetricMatrix
上定义的所有操作都会成功,因为两个类持有的数据是相同的)
问题
您是否预见到我的方法存在任何我没有想到的问题?
我的方法是否会因下一个 dotnet 版本而中断?
您认为有更简洁的方法来实现我想要的吗?我有一些想法,但似乎没有一个能顺利解决。例如,我无法通过
对哪些操作在父类中保留子类进行编码class Matrix<T> where T : Matrix
...
T ScaledBy(double other)
因为操作是否保留 Child 类是只有 Child 才能拥有的知识。例如,SymmetricPositiveDefiniteMatrix
不会被 ScaledBy
保留。
或者,我可以使用封装而不是继承并定义
class BaseMatrix
{
...lots of operations
}
...
class Matrix : BaseMatrix
{
private BaseMatrix _baseMatrix;
...lots of "OperationX => new Matrix(_baseMatrix.OperationX)"
}
class SymmetricMatrix : BaseMatrix
{
private BaseMatrix _baseMatrix;
...lots of "OperationX => preserving ? new SymmetricMatrix(_baseMatrix.OperationX) : new Matrix(_baseMatrix.OperationX);"
}
虽然编写代码非常令人难过,因为我必须手动将我对 BaseMatrix
所做的每个更改传播到目前四个额外的类,并且用户必须手动转换 SymmetricMatrix
在许多场景中都可以转换为 Matrix
。
最后,我可以简单地不提供子类,而是使用像 bool _isSymmetric
这样的标志,并通过更改/设置我所有方法中的标志来编码保持对称性/正性/...的操作。这也很可悲,因为:
然后用户将能够编写 Matrix.EigenvalueDecomposition()
只是为了在运行时使用 进行中断 您必须向我保证您的矩阵是对称的,因为我只为这种情况实现了 EigenvalueDecomposition
错误
很容易忘记重置未保留的标志,然后意外地运行假设对称的操作(BLAS 通过简单地忽略矩阵的一半来做到这一点)
我喜欢能够在类型系统而不是注释中指定,例如,我从 CholeskyFactor
返回的矩阵是下三角矩阵(约定不同,有些人可能期望上三角矩阵矩阵)
用户看不到当前设置了哪些标志,因此他们不知道我是否使用给定算法的“专用”版本,并且可能最终使用 .SetSymmetric()
为了安全,不必要到处都是。
最佳答案
除非我遗漏了一个要求,否则您可以使用泛型实现您想要的
一个(不那么简短的)例子:
public abstract class BaseMatrix<TMatrix> where TMatrix : BaseMatrix<TMatrix>
{
// Replace with how you actuallt are storing you matrix values
protected object _valueStore;
// common initialization (if required), if not keep empty
protected BaseMatrix()
{
}
// necessary to copy the value store.
protected BaseMatrix(object valueStore)
{
this._valueStore = valueStore;
}
public virtual TMatrix ScaledBy(double scalar)
{
// implementation
return default;
}
}
public class Matrix : BaseMatrix<Matrix>
{
}
public class SymmetricMatrix : BaseMatrix<SymmetricMatrix>
{
public SymmetricMatrix() : base(){}
// allows to build from another matrix, could be internal
public SymmetricMatrix(object valueStore) : base(valueStore){}
public override SymmetricMatrix ScaledBy(double scalar)
{
return base.ScaledBy(scalar);
}
}
public class SymmetricPositiveDefiniteMatrix : BaseMatrix<SymmetricPositiveDefiniteMatrix>
{
// If we *know* the type is not the same after this method call, we mask with a new one retirning the target type
// A custom cast operator will handle the conversion
public new SymmetricMatrix ScaledBy(double scalar)
{
return base.ScaledBy(scalar);
}
// Added to allow a cast between SymmetricPositiveDefiniteMatrix and SymmetricMatrix
// in this example, we keep the value store to not have to copy all the values
// Depending on project rules could be explicit instead
public static implicit operator SymmetricMatrix(SymmetricPositiveDefiniteMatrix positiveSymmetricMatrix)
{
return new SymmetricMatrix(positiveSymmetricMatrix._valueStore);
}
}
这将使 ScaledBy(double)
方法在每种类型的矩阵中可用,并返回调用它的矩阵的类型。
而且它符合您的要求,不必重新定义每个类中的大多数方法/属性。
显然,您可以覆盖子类中的方法,以便在 base()
之前或之后执行更多操作调用甚至定义一个完全不同的实现。
一个缺点是如果您需要一种类型来继承自 BaseMatrix<TMatrix>
的类.您无法更改泛型类型参数。
或者,如果这真的不符合您的需求并且更喜欢走封装路线,您可以看看 source generators因为代码似乎很重复。
关于c# - 比 Unsafe.As 转换到子类更好的方法来解决我的类层次结构问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74122649/
我正在尝试将多个水平链接的 Button 和 TextView 垂直链接为 View 集,但仍保持平面 View 层次结构。这是我的初始布局和代码:
到目前为止,我已经在Google BigQuery上训练了几种模型,目前我需要查看模型的外观(即架构,损失函数等)。 有没有办法获取这些信息? 最佳答案 仔细阅读文档后,我可以说该功能尚不存在。我什至
本文实例讲述了PHP实现二叉树深度优先遍历(前序、中序、后序)和广度优先遍历(层次)。分享给大家供大家参考,具体如下: 前言: 深度优先遍历:对每一个可能的分支路径深入到不能再深入为止,而且每个
我是一名优秀的程序员,十分优秀!