Есть два подхода, чтобы справиться, перенести линию кода
string[] row = new string[rd.FieldCount];
сюда
while (rd.Read())
{
сразу после фигурной скобки, или изменить линию кода
rows.Add(row.Clone());
Причина, array это "reference type", познакомиться с описание reference type можно
здесь, ключ к пониманию следующий абзац:
With reference types, two variables can reference the same object; therefore, operations on one variable can affect the object referenced by the other variable.
. Точнее, что такое reference type потребует отладчик и работу с MSIL. Вот как описывает reference type
MSIL standard:
I.8.2.1 Value types and reference types
There are two kinds of types: value types and reference types.
[...]
Reference types –A value described by a reference type denotes the location of another
value.
По этой причине, не смотря на то, что вы трижды сместили строку в DataReader, запись каждый раз производилась в один и тот же блок данных, переписывая его, а три записи в неизвестной лист были обращены к одному и тому же блоку.