Home > Enterprise >  Returning a 2D matrix method in C#
Returning a 2D matrix method in C#

Time:10-10

I'm learning C# and I came across to linear algebra and matrices. I'm aiming to make a class that takes a 2D matrix with given values through input and print the elements of the matrix. With this class, I'm planning to have access to some methods that allows do linear algebra calculations like transformations (rotation, scaling, translation) and other arithmetic operations (e.g adding, multiplication, etc), and miscellaneous methods such as print.

To keep it simple, I have something, but now I'm stuck with an approach for printing the 2D matrix that I'm trying to do. Basically, I'm creating a constructor that takes the size of the array (x and y) in my class and then just prints it inside of the constructor. However, my goal is to have the values of the matrix creation and use it for my print method. This print method will call that matrix and print the matrix with the elements. I'm having difficulties to wrap around how to return the array by itself and elements in it for just a separate method function of my class. It works fine inside of the constructor, but the whole idea is to have a return value and use it for later (e.g like print in this case).

CODE:

using System;
namespace Vectors_Matrices
{   
    public class Matrices
    {
        public int x;
        public int y;
        public Matrices()
        {
            Console.WriteLine("Matrices constructor created...");
        }
        public Matrices(int value)
        {
            this.x = value;
            this.y = value;
        }
        public Matrices(int x, int y)
        {
            int[,] array2D = new int[x, y];
            Console.WriteLine("2D Created with [{0}, {1}] dimensions", x, y);
            for (int i = 0; i < x; i  )
            {
                for (int j = 0; j < y; j  )
                {
                    Console.Write("Array Index [{0}, {1}]: ", i, j);
                    array2D[i, j] = Convert.ToInt32(Console.ReadLine());
                }
            }

            for (int i = 0; i < x; i  )
            {
                for (int j = 0; j < y; j  )
                {
                    if (j == 0)
                        Console.Write(array2D[i, j]);
                    else
                        Console.Write(" "   array2D[i, j]);
                }
                Console.WriteLine();
            }
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            Console.Write("Insert your x value for the 2D matrix: ");
            int x = Convert.ToInt32(Console.ReadLine());
            Console.Write("Insert your y value for the 2D matrix: ");
            int y = Convert.ToInt32(Console.ReadLine());

            Matrices myMatrix = new Matrices();
            Matrices my2DMatrix = new Matrices(x, y);
        }
    }
}

I came across with few ideas that involves with ref and out, but I'm not quite confident enough to know how to properly use it for my case. I know I would use it for the arithmetic and maybe transformation, but not for printing.

Let me know if you need clarifications or anything. Once solved, I will mark this as "Solved". Feel free to share different approaches while keeping the same format.

CodePudding user response:

I would recommend moving your 2D array declaration as a field or property of your Matrices class and write a separate method that prints the matrix like ToConsole(). This method will have access to the instance fields/properties of the Matrices class.

Also as a sidenote - it's generally conventional to name your classes as singular entities (so in this case Matrix vs Matrices) unless the class specifically represents a collection of items.

Here's some example code:

using System;
namespace Vectors_Matrices
{
    public class Matrix
    {
        public int x;
        public int y;
        private int[,] array2D;

        public Matrix(int value)
        {
            x = value;
            y = value;
            array2D = new int[x, y];
            // this.z = value; what's this about?
        }

        public Matrix(int x, int y)
        {
            this.x = x;
            this.y = y;

            array2D = new int[x, y];
            Console.WriteLine("2D Created with [{0}, {1}] dimensions", x, y);
            for (int i = 0; i < x; i  )
            {
                for (int j = 0; j < y; j  )
                {
                    Console.Write("Array Index [{0}, {1}]: ", i, j);
                    array2D[i, j] = Convert.ToInt32(Console.ReadLine());
                }
            }
        }

        public void ToConsole()
        {
            for (int i = 0; i < x; i  )
            {
                for (int j = 0; j < y; j  )
                {
                    if (j == 0)
                        Console.Write(array2D[i, j]);
                    else
                        Console.Write(" "   array2D[i, j]);
                }
                Console.WriteLine();
            }
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            Console.Write("Insert your x value for the 2D matrix: ");
            int x = Convert.ToInt32(Console.ReadLine());
            Console.Write("Insert your y value for the 2D matrix: ");
            int y = Convert.ToInt32(Console.ReadLine());

            Matrix myMatrix = new Matrices();
            Matrix my2DMatrix = new Matrix(x, y);

            my2DMatrix.ToConsole();
        }
    }
}

CodePudding user response:

The problem is that you define your array in the constructor. If you define it publicly in the class, it can be accessed from constructor and any other methods like Print.

using System;
namespace Vectors_Matrices
{   
    public class Matrices
    {
        public int x;
        public int y;
        public int[,] array2D;

        public Matrices()
        {
            Console.WriteLine("Matrices constructor created...");
        }
        public Matrices(int value)
        {
            this.x = value;
            this.y = value;
            this.z = value;
        }
        public Matrices(int x, int y)
        {
            array2D = new int[x, y];
            Console.WriteLine("2D Created with [{0}, {1}] dimensions", x, y);
            for (int i = 0; i < x; i  )
            {
                for (int j = 0; j < y; j  )
                {
                    Console.Write("Array Index [{0}, {1}]: ", i, j);
                    array2D[i, j] = Convert.ToInt32(Console.ReadLine());
                }
            }
        }
        public void Print()
        {
            for (int i = 0; i < x; i  )
            {
                for (int j = 0; j < y; j  )
                {
                    if (j == 0)
                        Console.Write(array2D[i, j]);
                    else
                        Console.Write(" "   array2D[i, j]);
                }
                Console.WriteLine();
            }
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            Console.Write("Insert your x value for the 2D matrix: ");
            int x = Convert.ToInt32(Console.ReadLine());
            Console.Write("Insert your y value for the 2D matrix: ");
            int y = Convert.ToInt32(Console.ReadLine());

            Matrices myMatrix = new Matrices();
            Matrices my2DMatrix = new Matrices(x, y);
            my2DMatrix.Print();
        }
    }
}

CodePudding user response:

Do not do this.

public Matrices(int x, int y, out int[,] matrix)
{
    int[,] array2D = new int[x, y];
    // Read user input x*y times to fill array2D
    matrix = array2D;
}   

Because Constructors should return fast, reading input from user while creating the object is slowing the creation and is considered a bad practice, you can create the matrix explicitly via a separate method.


A possible refactoring could be like this:

Step 1. Force passing the dimensions when creating the matrix (set the empty ctor as private)..

private readonly int _x;
private readonly int _y;
public int[,] MyMatrix { private set; get; }

private Matrix()
{
}

public Matrix(int dim) : this(dim, dim)
{
}

public Matrix(int dim1, int dim2)
{
    ValidateDimensions(dim1, dim2); // defined later
    _x = dim1;
    _y = dim2;
    Console.WriteLine("Matrix constructor created...");
}

Step 2. Create the matrix explicitly

public int[,] CreateNewMatrix()
{
    if (_x == 0 || _y == 0) return MyMatrix = new int[0, 0];
    var array2D = new int[_x, _y];
    Console.WriteLine("2D Created with [{0}, {1}] dimensions", _x, _y);
    for (int i = 0; i < _x; i  )
    {
        for (int j = 0; j < _y; j  )
        {
            Console.Write("Array Index [{0}, {1}]: ", i, j);
            array2D[i, j] = Convert.ToInt32(Console.ReadLine());
        }
    }

    return MyMatrix = array2D;
}

It's allowed to reset the dimensions when creating the matrix

private bool ValidateDimensions(int dim1, int dim2)
{
    if (dim1 < 0 || dim2 < 0) throw new Exception("It's not allowed to create a matrix with negative dimension..");
}

public int[,] CreateNewMatrix(int dim1, int dim2)
{
    ValidateDimensions(dim1, dim2);
    _x = dim1;
    _y = dim2;
    var newMatrix = CreateNewMatrix();
    return newMatrix;
}

public int[,] CreateNewMatrix(int dim){
    var newMatrix = CreateNewMatrix(dim, dim);
    return newMatrix;
}

Step 3. Printing the matrix would be a static method

public static void PrintMatrix(int[,] array2D)
{
    if (array2D == null || array2D.Length == 0) 
    {
        Console.WriteLine($"{nameof(PrintMatrix)}: Input array is empty..");
        return;
    }
    
    for (int i = 0; i < array2D.GetLength(0); i  )
    {
        for (int j = 0; j < array2D.GetLength(1); j  )
        {
            if (j == 0)
                Console.Write(array2D[i, j]);
            else
                Console.Write(" "   array2D[i, j]);
        }

        Console.WriteLine();
    }
}

Example Usage

public static void Main(string[] args)
{
    Console.Write("Insert your x value for the 2D matrix: ");
    int x = Convert.ToInt32(Console.ReadLine());
    Console.Write("Insert your y value for the 2D matrix: ");
    int y = Convert.ToInt32(Console.ReadLine());
    
    var matrix = new Matrix(x, y);
    matrix.CreateNewMatrix();
    Matrix.PrintMatrix(matrix.MyMatrix);
}
  • Related