If you are asking how you would set up a collection to simply use it to move through each element without using an array structure, simply put your objects into an ArrayList. ArrayList elements simply assume the type of object being stored in them.
With ArrayLists however, you can use multiple types but you will have to use a little reflection to extract information from each of the elements.
The sample code shown above that looks at this problem from the inheritance point of view is an excellent way to go if you like using this type of paradigm. However, inheritance has its drawbacks in that it is probably as inefficient as using reflection to any extent. And the more complex\heavy your objects are, the more inefficient inheritance becomes. In addition, anything beyond simple inheritance hierarchies often become unmanageable over time and this has been well documented over the years. Most large projects that use extensive inheritance have often become maintenance nightmares for its developers.
I am not saying do not use inheritance but just to be careful if you do.
The code I put together for you rather quickly below provides a somewhat primitive but simplistic method to do the same thing but using reflection. Reflection’s inefficiencies come from the need to for casting objects, which as other posters have rightfully stated forces the boxing and unboxing of objects.
Despite the inefficiencies of both paradigms, such inefficiencies are often not noticeable to the developer or user of an application until you begin working with large numbers of objects. Too often developers prioritize performance over common-sense coding techniques for small numbers of processes involved. The result is that a lot of effort is wasted on finessing internal efficiencies that often provide little advantage. Further, today’s compilers are so highly optimized that they will often make up for such optimizations no matter what paradigm you eventually decide to implement.
So for the code… I hope it helps… 
C# Main Class
using System;
using System.Reflection;
using System.Collections;
using System.Threading.Tasks;
namespace ArrayListOfObjects
{
class Program
{
static void Main(string args)
{
ArrayList ObjectArrayList = new ArrayList();
Class1 loClass1 = new Class1();
Class2 loClass2 = new Class2();
ObjectArrayList.Add(loClass1);
ObjectArrayList.Add(loClass2);
foreach (object loObject in ObjectArrayList)
{
var loObject1 = loObject.GetType();
switch (loObject1.Name)
{
case "Class1":
Class1 loNewClass1 = new Class1();
loNewClass1 = (Class1)loObject;
Console.WriteLine("String ID: " + loNewClass1.STRING_ID);
break;
case "Class2":
Class2 loNewClass2 = new Class2();
loNewClass2 = (Class2)loObject;
Console.WriteLine("String ID: " + loNewClass2.STRING_ID);
break;
}
}
Console.ReadLine();
}
}
}
C# Class1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ArrayListOfObjects
{
internal class Class1
{
internal Class1()
{
}
string csStringID = "1";
internal string STRING_ID
{
get { return csStringID; }
}
internal string Get_String1()
{
return ("my string1");
}
}
}
C# Class2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ArrayListOfObjects
{
internal class Class2
{
internal Class2()
{
}
string csStringID = "2";
internal string STRING_ID
{
get { return csStringID; }
}
internal string Get_String2()
{
return ("my string2");
}
}
}