What's the magic of arrays in C#

后端 未结 8 1064
生来不讨喜
生来不讨喜 2020-12-09 08:56
int[] a = new int[5];
string[] b = new string[1];

The types of both a and b inherit from the abstract System.Array<

相关标签:
8条回答
  • 2020-12-09 09:38

    Look at the Array class.

    When declaring an array using the [] syntax, the compiler, behind the scenes will use this class for you.

    For C#, [] becomes a type that inherits from System.Array.

    From the C# 4.0 spec:

    §12.1.1 The System.Array type

    The type System.Array is the abstract base type of all array types. An implicit reference conversion (§6.1.6) exists from any array type to System.Array, and an explicit reference conversion (§6.2.4) exists from System.Array to any array type. Note that System.Array is not itself an array-type. Rather, it is a class-type from which all array-types are derived.

    0 讨论(0)
  • 2020-12-09 09:38

    I would recommend getting the ECMA 335 spec and looking for Arrays if you want to know the low level detail: http://www.ecma-international.org/publications/standards/Ecma-335.htm

    0 讨论(0)
  • 2020-12-09 09:41

    There is such class. You cannot inherit it, but when you write "int[]" the compiler creates a type that inherits System.Array. So if you declare a variable:

    int[] x;
    

    This variable will have a type that inherits System.Array, and therefore has all its methods and properties.

    This is also similar to delegates. When you define a delegate:

    delegate void Foo(int x);
    delegate int Bar(double x);
    

    Then the type Foo is actually a class that inherits System.MulticastDelegate and Bar is a class that inherits System.Delegate.

    0 讨论(0)
  • 2020-12-09 09:44

    Arrays are special to CLR. They're allocated with 'newarr' instruction, and elements are accessed with 'ldelem*' and 'stelem*' instructions, not via System.Array methods;

    see http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.newarr.aspx

    You can check out ildasm output to see how arrays are represented.

    So, to answer your question - no new type declaration is generated for any particular array.

    0 讨论(0)
  • 2020-12-09 09:44

    [] is a syntax(syntatic sugar) for defining Arrays in c#. Maybe CreateInstance will be replaced at runtime

     Array a = Array.CreateInstance(typeof(int), 5); 
    

    is same as

    int[] a = new int[5];
    

    Source for CreateInstance (taken from reflector)

    public static unsafe Array CreateInstance(Type elementType, int length)
    {
        if (elementType == null)
        {
            throw new ArgumentNullException("elementType");
        }
        RuntimeType underlyingSystemType = elementType.UnderlyingSystemType as RuntimeType;
        if (underlyingSystemType == null)
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "elementType");
        }
        if (length < 0)
        {
            throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
        }
        return InternalCreate((void*) underlyingSystemType.TypeHandle.Value, 1, &length, null);
    }
    
    0 讨论(0)
  • 2020-12-09 09:45

    And why did they(the c# team) make this design(I mean why it's not something like Array...

    Generics are ideal for defining a container, as they constrain the element type so you can't insert type A and try to retrieve type B.

    But generics were not added until CLR2/C#2. So arrays had to provide type safety in their own way.

    Even so, it's not that different to generics. You note that there is no special class for int[]. But nor would there be for Array<int>. In generics there would only be the generic class Array<T>, and the CLR "magically" creates specialised versions for distinct type argument you use. So it would be no less "magic" if generics were used.

    Despite this, in the CLR the type of any object is reified (it exists as a value you can manipulate), of type Type, and can be obtained with typeof. So although there is no code declaration of any array type (and why would you need to see it?) there is a Type object that you can query.

    By the way, there was a design flaw in the way arrays constrain element types. You can declare an array:

    int[] ints = ...
    

    You can then store it in a looser variable:

    object[] objs = ints;
    

    But that means you can insert a string (at least it appears so at compile time):

    objs[3] = "Oh dear";
    

    At runtime it throws an exception. The idea of static type checking is to catch this kind of thing at compile time, not runtime. Generics would not have had this problem because they don't give assignment compatibility to generic class instances based on the compatibility of their type parameters. (Since C#4/CLR4 they have gained the ability to do that where it makes sense, but that wouldn't make sense for a mutable array.)

    0 讨论(0)
提交回复
热议问题