Array index return null instead of out of bound

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];
}

There's really not much else you can do here than just:

if (i >= array.Length) return null;
else return array[i];

or, using the ? operator:

return (i >= array.Length) ? null : array[i];

OK, whole new approach. Since you have several possible types and want a "joker" method, you can store the values as key/value collection in your class then such method becomes possible.

First, to store the values internally:

public class TestClass
{
     private Dictionary<Type, Array> _values = new Dictionary<Type, Array>();
}

Now to populate that collection with actual data:

_values.Add(typeof(int?), new int[] { 1, 2, 3 });
_values.Add(typeof(string), new string[] { "a", "b", "c", "d", "e" });

And finally the joker method:

public T Get<T>(int index)
{
    Type type = typeof(T);
    Array array;
    if (_values.TryGetValue(type, out array))
    {
        if (index >= 0 && index < array.Length)
        {
            return (T)array.GetValue(index);
        }
    }
    return default(T);
}

Usage:

for (int i = 0; i < 10; i++)
{
  int? id = testClass.Get<int?>(i);
  string name = testClass.Get<string>(i);
  //...
}