如何修复C#中由泛型引起的CS0029错误

时间:2019-04-08 09:55:38

标签: c# generics

我正在尝试在类Parse中编写一个静态Matrix<T, V>方法,该方法负责根据字符串构造正确尺寸的Matrix<T, Vector<T>>(在此类中,支持矩阵按行向量)。存在Matrix<T, V>的几个子类(例如Matrix2x<T>Matrix2x2<T>等)。除了不同的获取/设置可访问性之外,不同的子类还具有不同的维度。该代码是从现有的功能Java代码改编而成。我和一个朋友正在尝试使用C#代替Java,这是我们更加熟悉的。

问题在于这些参数化的子类无法(隐式或强制转换)转换为用Vector<T>基类参数化的基类。我不清楚以下代码为什么不编译,尽管我认为这是C#泛型与Java泛型相比的具体性造成的。

我想知道编译错误是否可能是由于尝试返回由类型Vector<T>类型化的Matrix引起的,因为它是抽象的。将Vector<T>更改为具体类(具有伪方法)并不能解决问题;编译错误仍然存​​在。

public static Matrix<T, Vector<T>> Parse(Func<string, Scalar<T>> parser, string str, bool mutable = false) {
    MutableVector2D<T> mv2 = new MutableVector2D<T>();
    Vector2D<T> v2 = mv2;
    Vector<T> v = v2;

    MutableMatrix2x2<T> mm22 = new MutableMatrix2x2<T>();
    Matrix2x2<T, MutableVector2D<T>> m22 = mm22;
    Matrix2x2<T, Vector2D<T>> m22_ = m22; // Does not compile (compilation error CS0029)
    Matrix2x<T, Vector2D<T>> m2 = m22_;
    Matrix<T, Vector2D<T>> m = m2;
    Matrix<T, Vector<T>> answer = m; // Does not compile (compilation error CS0029)
    return answer;
}

如代码片段所示,MutableVector2D<T>可以隐式转换为Vector2D<T>Vector<T>。但是,MutableMatrix2x2<T>可能隐式转换为Matrix2x2<T, MutableVector2D<T>>,而不是Matrix2x2<T, Vector2D<T>>,这使我感到困惑。强制转换为Matrix2x2<T, Vector2D<T>>(因为我了解这个问题,这没有必要)解决了任何问题。

下面列出了相关的类标题:

public sealed class MutableVector2D<T> : Vector2D<T> {...}
public abstract class Vector2D<T> : Vector<T> {...}
public abstract class Vector<T> : ICopyable<Vector<T>>, IParser<Vector<T>>, IComparable<Vector<T>>, IEnumerable<Scalar<T>> {...}

public sealed class MutableMatrix2x2<T> : Matrix2x2<T, MutableVector2D<T>> {...}
public abstract class Matrix2x2<T, V> : Matrix2x<T, V> where V : Vector2D<T> {...}
public abstract class Matrix2x<T, V> : Matrix<T, V> where V : Vector2D<T> {...}
public abstract class Matrix<T, V> : ICopyable<Matrix<T, V>>, IParser<Matrix<T, Vector<T>>>, IComparable<Matrix<T, Vector<T>>>, IEnumerable<Scalar<T>> where V : Vector<T> {...}

需要清楚的是,上面的Parse方法与实际的解析操作无关。这只是调试调试错误的一种尝试。如果有人想知道,以下是实际的,未编译的Parse方法:

public static Matrix<T, Vector<T>> Parse(Func<string, Scalar<T>> parser, string str, bool mutable = false) {
    string[] lines = str.Split('\n');
    int m = lines.Length;
    if (m == 0) {
        throw new ArgumentException("Cannot construct a Matrix with 0 rows.", "str");
    }
    string line = lines[0];
    int leftIndex = line.IndexOf('[') + 1;
    string[] entries = line.Substring(leftIndex, line.IndexOf(']', leftIndex)).Split(',');
    int n = entries.Length;
    if (n < 2) {
        throw new ArgumentException("Cannot construct a Matrix with fewer than 2 columns.");
    }
    Scalar<T>[,] parsedEntries = new Scalar<T>[m, n];
    for (int j = 0; j < n; j++) {
        parsedEntries[0, j] = parser.Invoke(entries[j]);
    }
    for (int i = 1; i < m; i++) {
        line = lines[i];
        leftIndex = line.IndexOf('[') + 1;
        entries = line.Substring(leftIndex, line.IndexOf(']', leftIndex)).Split(',');
        if (entries.Length != n) {
            throw new ArgumentException("Cannot construct a Matrix from a jagged array of entries", "str");
        }
        for (int j = 0; j < n; j++) {
            parsedEntries[i, j] = parser.Invoke(entries[j]);
        }
    }
    switch (n) {
        case 2:
            if (m == n) {
                if (mutable) {
                    return new MutableMatrix2x2<T>(parsedEntries); // Does not compile (compilation error CS0029)
                } else {
                    return new ImmutableMatrix2x2<T>(parsedEntries); // Does not compile (compilation error CS0029)
                }
            } else {
                if (mutable) {
                    return new MutableMatrix2x<T>(parsedEntries); // Does not compile (compilation error CS0029)
                } else {
                    return new ImmutableMatrix2x<T>(parsedEntries); // Does not compile (compilation error CS0029)
                }
            }
        case 3:
            if (m == n) {
                if (mutable) {
                    return new MutableMatrix3x3<T>(parsedEntries); // Does not compile (compilation error CS0029)
                } else {
                    return new ImmutableMatrix3x3<T>(parsedEntries); // Does not compile (compilation error CS0029)
                }
            } else {
                if (mutable) {
                    return new MutableMatrix3x<T>(parsedEntries); // Does not compile (compilation error CS0029)
                } else {
                    return new ImmutableMatrix3x<T>(parsedEntries); // Does not compile (compilation error CS0029)
                }
            }
        case 4:
            if (m == n) {
                if (mutable) {
                    return new MutableMatrix4x4<T>(parsedEntries); // Does not compile (compilation error CS0029)
                } else {
                    return new ImmutableMatrix4x4<T>(parsedEntries); // Does not compile (compilation error CS0029)
                }
            } else {
                if (mutable) {
                    return new MutableMatrix4x<T>(parsedEntries); // Does not compile (compilation error CS0029)
                } else {
                    return new ImmutableMatrix4x<T>(parsedEntries); // Does not compile (compilation error CS0029)
                }
            }
        default:
            if (m == n) {
                if (mutable) {
                    return new MutableMatrixNxN<T>(parsedEntries); // Does not compile (compilation error CS0029)
                } else {
                    return new ImmutableMatrixNxN<T>(parsedEntries); // Does not compile (compilation error CS0029)
                }
            } else {
                if (mutable) {
                    return new MutableMatrixNx<T>(parsedEntries); // Does not compile (compilation error CS0029)
                } else {
                    return new ImmutableMatrixNx<T>(parsedEntries); // Does not compile (compilation error CS0029)
                }
            }
    }
}

在此先感谢您能为我提供的任何帮助。

0 个答案:

没有答案