Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array index return null instead of out of bound

I am currently trying to implement an "indexed" property within my class definition.

For example I have the following class:

public class TestClass
{
   private int[] ids = null;

   public string Name { get; set; }
   public string Description { get; set; }
   public int[] Ids { 
      get
      {
         //Do some magic and return an array of ints 
         //(count = 5 - in this example in real its not fixed)
         return _ids;
      }
   }
}

Now I like to use this class as the following:

private void DoSomething()
{
   var testClass = GetSomeTestClass();
   //work with the ids

   for (int i = 0; i < 10; i++) //I know I could say i < Ids.Length, its just an example
   {
      int? id = testClass.Ids[i];
      //this will result, in a out of bound exception when i reaches 5 but I wish for it to return a null like a "safe" index call ?!?
   }
}

So is there a safe index call that results in a null, without the need for me to wrap it again and again in a try catch.

Another thing I dont wish to use the class index, because I need several properties that work like this, with different types (int, string, bool, custom class and so on).

(Again the for is just a simple example, I know I could in this case say "i < Ids.Length")

like image 290
Rand Random Avatar asked Nov 06 '13 10:11

Rand Random


People also ask

How to avoid array index out of bound exception?

To avoid the ArrayIndexOutOfBoundsException , the following should be kept in mind: The bounds of an array should be checked before accessing its elements. An array in Java starts at index 0 and ends at index length - 1 , so accessing elements that fall outside this range will throw an ArrayIndexOutOfBoundsException .

What does index was outside the bounds of the array mean?

Index was outside the bounds of the array. That error message usually means that you have called for an object in the array at a location that is null, or has nothing there.

How do you know if an index is bound?

Another way of checking if an array is out of bounds is to make a function. This will check if the index is "in bounds". If the index is below zero or over the array length you will get the result false. This should be built in as a member function of the array class..


1 Answers

If you were only interested in already non-nullable type data e.g. struct you could have gotten away with a simple extension method e.g.

public static class ArrayExt
{
    public static Nullable<T> GetValueOrNull(this T[] array, int index) where T: struct
    {
        return array.Length < index ? new Nullable<T>(array[index]) : null;
    }
}

which would have allowed you to simply call

int? id = testClass.Ids.GetValueOrNull(i);

However, given you need to support an arbitrary number of types my suggestion would be to implement a wrapper around an array and take control over how you access the data e.g.

public class SafeArray<T>
{
    private T[] items;

    public SafeArray(int capacity)
    {
        items = new T[capacity];
    }

    public object this[int index]
    {
        get
        {
            return index < items.Length ? (object)items[index] : null;
        }
        set
        {
            items[index] = (T)value;
        }
    }
}

public class TestClass
{
    public TestClass()
    {
        Ids = new SafeArray<int>(5);
        Instances = new SafeArray<MyClass>(5);
    }
    ...
    public SafeArray<int> Ids { get; private set; }

    public SafeArray<MyClass> Instances { get; private set; }
}

The key to this approach is to use object as the return type. This allows you to cast (or box/unbox if using value types) the data to the expected type on the receiving end e.g.

for (int i = 0; i < 10; i++)
{
    // we need an explicit cast to un-box value types
    var id = (int?)testClass.Ids[i];
    // any class is already of type object so we don't need a cast
    // however, if we want to cast to original type we can use explicit variable declarations e.g.
    MyClass instance = testClass.Instances[i];
}
like image 61
James Avatar answered Oct 09 '22 16:10

James