C# Синтаксис инициализации коллекции для использования с пользовательским классом матрицы?

Я создаю пользовательский класс матрицы, который имеет только один 2D-массив для хранения всего (я знаю, что 1D-массив быстрее и лучше, но не в этом смысл этой реализации), дело в том, что я хотел бы иметь конструктор, и сможет сделать что-то вроде

Matrix a = new Matrix(2,2){{1,2},{3,4}};

и все получится. Я столкнулся с "Матрица" не содержит определения для "Добавить" и нет метода расширения "Добавить" и т. Д." но после осмотра я еще не смог найти достаточно надежной информации о том, как определить метод Add(), чтобы он работал. Вот код у меня пока

public class Matrix : IEnumerable
    {
        /* What we know abuot matricies
         * - matricies are defined by rows, cols
         * - addition is element-wise
         */

        public IEnumerator GetEnumerator()
        {
            yield return m;
        }

        private void Add(double a)
        {
            // what exactly should go here anyway?
        }

        private double[,] m;

        public double this[int rows, int cols]
        {
            get => m[rows, cols];
            set => m[rows, cols] = value;
        }       

        public Matrix(int rows, int cols)
        {
            m = new double[rows, cols];
        }
    ...
    }

Итак, как бы я все-таки сделал метод Add()?

2 ответа

Решение

Попробуйте этот код. Ваш метод Add должен быть общедоступным. Кроме того, чтобы сделать код безопасным, вы должны добавить верификаторы, чтобы проверить, соответствуют ли размеры m Матрица и предоставленные данные совпадают.

private int currentRow = 0;
public void Add(params double[] a)
{
    for (int c = 0; c < a.Length; c++)
    {
        m[currentRow, c] = a[c];
    }
    currentRow++;
}

Если вы не предоставите все строки, оставшиеся строки будут иметь элементы со значениями по умолчанию. Также обратите внимание, что этот метод может быть вызван в будущем, и он вызовет исключение, когда матрица m заполнит все строки.

Я знаю, что опаздываю, но как насчет метода расширения double[,]или даже реализовать неявное приведение?

class Matrix
{
    // Implicit cast
    public static implicit operator Matrix(double[,] array) => new Matrix(array);

    private double[,] source;
    public Matrix(double[,] source)
    {
        this.source = source;
    }
}
static class Extensions
{
    // Extension
    public static Matrix ToMatrix(this double[,] array)
    {
        return new Matrix(array);
    }
}
static class Program
{
    static void Main()
    {
        // Extension
        Matrix a = new double[,] {
            { 1.0, 2.0, 3.0 },
            { 1.0, 2.0, 3.0 },
            { 1.0, 2.0, 3.0 }
        }.ToMatrix();

        // Implicit cast
        Matrix b = new double[,] {
            { 1.0, 2.0, 3.0 },
            { 1.0, 2.0, 3.0 },
            { 1.0, 2.0, 3.0 }
        };
    }
}

Ответ Магнетрона - это способ сделать это, если вы хотите использовать синтаксис инициализатора коллекции. Это будет лучше работать с зубчатым массивом вместо двумерного массива; как он указывает, невозможно выполнить проверку во время компиляции, чтобы убедиться, что число аргументов в инициализаторе соответствует размеру матрицы, поэтому вы рискуете ошибками во время выполнения просто инициализировать класс.

Другой подход заключается в реализации альтернативного конструктора, который позволяет инициализировать матрицу, например так:

public Matrix(double[,] source)
{
    m = source;
}

Тогда ваша строка кода будет выглядеть так:

Matrix a = new Matrix(new double[,]{ {1,2},{3,4} });

Это позволило бы избежать этой проблемы, поскольку размеры матрицы определяются размерами данных инициализации, которые должны представлять собой двумерный массив.

Другие вопросы по тегам