Per renderlo il più pulito possibile, mi piace lasciare che il compilatore faccia tutto il lavoro. Non ci sono cast (quindi è effettivamente indipendente dai tipi). Non vengono utilizzate librerie di terze parti (System.Linq) (nessun overhead di runtime).
public static IEnumerable<T> GetEnumerable<T>(this T[] arr)
{
return arr;
}
// E per usare il codice:
String[] arr = new String[0];
arr.GetEnumerable().GetEnumerator()
Questo sfrutta un po 'di magia del compilatore che mantiene tutto pulito.
L'altro punto da notare è che la mia risposta è l'unica che eseguirà il controllo in fase di compilazione.
Per una qualsiasi delle altre soluzioni, se il tipo di "arr" cambia, il codice chiamante verrà compilato e avrà esito negativo in fase di esecuzione, determinando un bug di runtime.
La mia risposta farà sì che il codice non venga compilato e quindi ho meno possibilità di inviare un bug nel mio codice, poiché mi segnalerebbe che sto usando il tipo sbagliato.