Array.AsReadOnlyメソッドを使うことで、配列を元に読み取り専用のコレクションを作成することが出来ます。

Array.AsReadOnlyメソッドを使って配列の読み取りビューを作成する
using System;
using System.Collections.ObjectModel;

class Sample {
  static void Main()
  {
    int[] source = {0, 1, 2, 3, 4};

    // 配列を読み取り専用にする
    ReadOnlyCollection<int> arr = Array.AsReadOnly(source);

    // 要素を列挙
    for (int i = 0; i < arr.Count; i++) {
      Console.Write("{0}, ", arr[i]);
    }
    Console.WriteLine();

    // 読み取り専用のため、要素の設定は出来ない
    // sample.cs(20,5): error CS0200: プロパティまたはインデクサー 'System.Collections.ObjectModel.ReadOnlyCollection<int>.this[int]' は読み取り専用なので、割り当てることはできません。
    //arr[1] = 5;

    // IListインターフェイスを経由して、無理やり要素を変更しようとする
    (arr as System.Collections.IList)[0] = 5;
  }
}
実行結果
0, 1, 2, 3, 4,

ハンドルされていない例外: System.NotSupportedException: コレクションは読み取り専用です。
   場所 System.Collections.ObjectModel.ReadOnlyCollection`1.System.Collections.IList.set_Item(Int32 index, Object value)
   場所 Sample.Main()

Array.AsReadOnlyメソッドの戻り値はReadOnlyCollectionで、これは読み取り専用にした配列のように振る舞います。 例えば、インデックスを指定して要素に値を設定しようとするとコンパイルエラーとなり、IList等のインターフェイスにキャストして無理やり変更しようとしてもNotSupportedExceptionがスローされます。

それ以外の操作、例えば要素の参照や値の列挙は、通常の配列と同様に振る舞います。 なお、通常の配列と異なりReadOnlyCollectionにはLengthプロパティが無いので、代わりにCountプロパティを参照します。

ReadOnlyCollectionについてより詳しくは汎用ジェネリックコレクション(1) Collection/ReadOnlyCollection §.ReadOnlyCollectionを参照してください。