0

I am coding in C# and I have a class with a property of type List<List<T>> that gets initialized in the constructor. The code is as follows:

public class MyMatrix<T>
{
    private readonly List<List<T>> matrix;

    public MyMatrix(int dimension)
    {
        this.matrix = new List<List<T>>();
        for (int i = 0; i < dimension; i++)
        {
            List<T> subList = new List<T>();
            this.matrix.Add(subList);
        }
    }
    .....

The problem is that if I create a new object of type MyMatrix the sublists are empty so if I invoke the ToString() method of the class or any other method that returns the values contained in the sublists I get an OutOfOrder Exception as expected. Get and Set methods are as follows:

public T Get(int row, int column)
    {
        return this.matrix[row][column];
    }

public void Set(int row, int column, T value)
    {
        this.matrix[row].Insert(column, value);
    }

If I initialize the sublists with a Set method then everything is fine obviously. I can't change the constructor as it is up to the user of the class to initialize the sublists so it is not possible to know in advance what they are going to contain. How would you manage the exceptions in the class methods or would you bother at all?

9
  • if (this.matrix[row].Length < column - 1) { throw new ArgumentException(); }? Commented Sep 14, 2015 at 9:49
  • check if lists are empty and return some default, for example in ToString() you can return string.Empty. Calling ToString on empty matrix shouldn't be an exception Commented Sep 14, 2015 at 9:50
  • 1
    MyMatrix.ToString() should know and respect the array sizes (possibly zero). Accessing non-existing elements from user code in a list is a logical/application error and is correct to throw. I do not quite understand the problem (seriously). @wudzik Yes, returning a default prevents "crashing" but may just camouflage serious errors. Commented Sep 14, 2015 at 9:54
  • @PeterSchneider yes, if you try to run ToString on non-existing element (row) it should throw exception. I understand that OP is saying that he runs ToString on empty Matrix just like: var m = new Matrix(); m.ToString() and it shouldn't throw. Commented Sep 14, 2015 at 9:59
  • Using Lists as a matrix probably isn't a good idea. Why not use fixed duel arrays or The Matrix class which has a lot of useful methods implemented already msdn.microsoft.com/en-us/library/… Commented Sep 14, 2015 at 10:01

2 Answers 2

1

There are several approaches on managing exceptions in your case, and it depends on how you want to use the matrix class:

  1. If you expect users to set values without initializing the row/column, then on the Set method I would just resize the list if necesary to accomodate the row/column arguments. You can always insert empty items in the list by using default(T) (this works both with value and reference objects). In this scenario, the Get method should check if the matrix coordinates exist and otherwise return default(T) so that no exceptions occurr.

  2. If you expect users to always initialize the matrix, then just leave it as it is and throw exceptions. This is a clear hint that the application is misbehaving and the programmer must take care of this.

  3. If you are trying to implement something like a Sparse Matrix, then using List<T> is not the best way and you should try another approach - for example using Dictionary<int, Dictionary<int, T>> or some sort of linked list. Anyway in this scenario, if you go for the Dictionary approach, you still need to take the same decisions as above (ie. throw if accessing a non existent coordinate or just return default(T))

Sign up to request clarification or add additional context in comments.

3 Comments

Regarding your second point: you don't want to leak framework exceptions like ArgumentOutOfRangeException("index") (List<T>) or KeyNotFoundException("key") (Dictionary<TKey, TValue>) from library code. Prevent the exception from being thrown and throw your own ArgumentOutOfRangeException("column").
@CodeCaster: using try and catch in all the methods that may throw the exception?
@UbuntuDude no. Like I said in my first comment, check the underlying collection for the requested key, and if it doesn't exist, throw an exception yourself.
1

What about C# 6.0?

public T Get(int row, int column)
{
    return this.matrix[row]?[column] ?? default(T);
}

1 Comment

What if T is not nullable?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.