12.1 Array Types 12.1.2 Arrays and the Generic IList Interface A one-dimensional array T[] implements the interface System.Collections.Generic. IList<T> (IList<T> for short) and its base interfaces. Accordingly, there is an implicit conversion from T[] to IList<T> and its base interfaces. In addition, if there is an implicit reference conversion from S to T, then S[] implements IList<T> and there is an implicit reference conversion from S[] to IList<T> and its base interfaces (§6.1.6). If there is an explicit reference conversion from S to T, then there is an explicit reference conversion from S[] to IList<T> and its base interfaces (§6.2.4). For example: using System.Collections.Generic; class Test { static void Main() { string[] sa = new string[5]; object[] oa1 = new object[5]; object[] oa2 = sa; IList<string> IList<string> IList<object> IList<object> lst1 lst2 lst3 lst4 = = = = sa; oa1; sa; oa1; // // // // IList<string> lst5 = (IList<string>)oa1; IList<string> lst6 = (IList<string>)oa2; Okay Error: cast needed Okay Okay // Exception // Okay } } The assignment lst2 = oa1 generates a compile-time error since the conversion from object[] to IList<string> is an explicit conversion, not implicit. The cast (IList<string>) oa1 will cause an exception to be thrown at runtime since oa1 references an object[] and not a string[]. However, the cast (IList<string>)oa2 will not cause an exception to be thrown since oa2 references a string[]. Whenever there is an implicit or explicit reference conversion from S[] to IList<T>, there is also an explicit reference conversion from IList<T> and its base interfaces to S[] (§6.2.4). When an array type S[] implements IList<T>, some of the members of the implemented interface may throw exceptions. The precise behavior of the implementation of the interface is beyond the scope of this specification. n n ERIC LIPPERT It's interesting to consider the counterfactual world in which the CLR had generic types in version 1. In that counterfactual world, there would probably be generic array types Array<T>, Array2<T>, and so on. In this world, declarations of complicated array types become more clear: An Array<Array2<int>> is a onedimensional array where every element is a two-dimensional array of integers. 627 www.it-ebooks.info 12. Arrays n n BILL WAGNER The fact that an array T[] implements the IList<T> by throwing exceptions for some methods is one of those troubling real-world problems for which there isn't a good solution. IList<T> has methods that add or remove elements. Arrays have a fixed size, however, and cannot support some of those methods. Even so, you want to use the random access to elements that exists in the IList<T> interface. 12.2 Array Creation ays Array instances are created by array-creation-expressions (§7.6.10.4) or by field or local variable declarations that include an array-initializer (§12.6). When an array instance is created, the rank and length of each dimension are established and then remain constant for the entire lifetime of the instance. In other words, it is not possible to change the rank of an existing array instance, nor is it possible to resize its dimensions. Arr An array instance is always of an array type. The System.Array type is an abstract type that cannot be instantiated. 12. Elements of arrays created by array-creation-expressions are always initialized to their default values (§5.2). 12.3 Array Element Access Arr ays Array elements are accessed using element-access expressions (§7.6.6.1) of the form A[I 1, I 2, ..., I N], where A is an expression of an array type and each I X is an expression of type int, uint, long, or ulong, or can be implicitly converted to one or more of these types. The result of an array element access is a variable—namely, the array element selected by the indices. 12. The elements of an array can be enumerated using a foreach statement (§8.8.4). 12.4 Array Members Every array type inherits the members declared by the System.Array type. 628 www.it-ebooks.info 12.5 Covariance Array 12.5 Array Covariance For any two reference-types A and B, if an implicit reference conversion (§6.1.6) or explicit reference conversion (§6.2.4) exists from A to B, then the same reference conversion also exists from the array type A[R] to the array type B[R], where R is any given rank-specifier (but the same for both array types). This relationship is known as array covariance. Array covariance, in particular, means that a value of an array type A[R] may actually be a reference to an instance of an array type B[R], provided an implicit reference conversion exists from B to A. Because of array covariance, assignments to elements of reference type arrays include a runtime check that ensures the value being assigned to the array element is actually of a permitted type (§7.17.1). For example: class Test { static void Fill(object[] array, int index, int count, object value) { for (int i = index; i < index + count; i++) array[i] = value; } static void Main() { string[] strings = new string[100]; Fill(strings, 0, 100, "Undefined"); Fill(strings, 0, 10, null); Fill(strings, 90, 10, 0); } } The assignment to array[i] in the Fill method implicitly includes a runtime check that ensures the object referenced by value is either null or an instance that is compatible with the actual element type of array. In Main, the first two invocations of Fill succeed, but the third invocation causes a System.ArrayTypeMismatchException to be thrown upon executing the first assignment to array[i]. The exception occurs because a boxed int cannot be stored in a string array. n n ERIC LIPPERT This is my candidate for "worst feature" of C#. It allows assignments to fail at runtime without any indication in the source code that such failure is possible. It imposes a performance cost on extremely common code to make a rare scenario go quickly; accessing an array of unsealed reference type safely happens much more often than covariant array conversions do. I much prefer the type-safe covariance that has been added to IEnumerable<T>. 629 www.it-ebooks.info 12. Arrays n n CHRIS SELLS I find myself using arrays so seldomly—even single-dimensional arrays, let alone multi-dimensional or jagged arrays—that the strange corner cases don't tend to matter much. Given the availability of List<T>, Dictionary<K, V>, and IEnumerable<T>, I'd be a happy guy without arrays at all. n n PETER SESToFT The necessity for the runtime check that Eric laments stems Arr ays from the array type being covariant in the element type ( Student[] being a subtype of Person[] when Student is a subtype of Person). This array covariance design weakness is shared with the Java programming language, where the situation is even worse: Because Java implements generics by erasure, there is no type object representing a generic type parameter at runtime, so the check cannot be performed if the array was created as new T[...] for some type parameter T, or as new Stack<Person>[...]. Hence Java must forbid the creation of an array whose element type is a type parameter or a type constructed as a type instance of a generic type. In C#, type parameters and constructed types are represented faithfully at runtime, so these restrictions on array creation do not exist. In the Scala language, which was born with generic types, the array type is invariant in the element type and the runtime check is not needed (but is likely to be performed anyway, when Scala is compiled to Java bytecode). n Arr ays BILL WAGNER Eric's comments go a long way toward explaining why the safe n covariance and contravariance added for generics in C# 4.0 are so important. Improving both speed and correctness with the same change is generally rare. Array covariance specifically does not extend to arrays of value-types. For example, no 12. conversion exists that permits an int[] to be treated as an object[]. 12.6 Array Initializers Array initializers may be specified in field declarations (§10.5), local variable declarations (§8.5.1), and array creation expressions (§7.6.10.4): { { 12. array-initializer: variable-initializer-listopt variable-initializer-list , } } 630 www.it-ebooks.info