How is it possible to read the values, let's say: '99' from an assembly containing this code?
using Sytem;
public class Class1
{
public Class1() {
// array initializer, want to read '99', '100'... from assembly
var a = new double[,] { { 1, 2, 3 }, { 99, 100, 101 } };
// ...
}
}
The method in ILDASM:
.method /*06000001*/ public hidebysig specialname rtspecialname
instance void .ctor() cil managed
// SIG: 20 00 01
{
// Method begins at RVA 0x2080
// Code size 29 (0x1d)
.maxstack 3
.locals /*11000001*/ init ([0] float64[0...,0...] a)
.language '{3F5162F8-07C6-11D3-9053-00C04FA302A1}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
// Source File 'c:\Users\heini19\Documents\Visual Studio 2013\Projects\WcfService1\ClassLibrary1\Class1.cs'
//000005: public Class1() {
IL_0000: /* 02 | */ ldarg.0
IL_0001: /* 28 | (0A)000011 */ call instance void [mscorlib/*23000001*/]System.Object/*01000001*/::.ctor() /* 0A000011 */
IL_0006: /* 00 | */ nop
IL_0007: /* 00 | */ nop
//000006: // array initializer, want to read '99', '100' etc.
//000007: var a = new double[,] { { 1, 2, 3 }, { 99, 100, 101 } };
IL_0008: /* 18 | */ ldc.i4.2
IL_0009: /* 19 | */ ldc.i4.3
IL_000a: /* 73 | (0A)000012 */ newobj instance void float64[0...,0...]/*1B000001*/::.ctor(int32,
int32) /* 0A000012 */
IL_000f: /* 25 | */ dup
IL_0010: /* D0 | (04)000001 */ ldtoken field valuetype '<PrivateImplementationDetails>{975506E6-7C24-4C2B-8956-C1B9CF8B80C4}'/*02000003*//'__StaticArrayInitTypeSize=48'/*02000004*/ '<PrivateImplementationDetails>{975506E6-7C24-4C2B-8956-C1B9CF8B80C4}'/*02000003*/::'$$method0x6000001-1' /* 04000001 */
IL_0015: /* 28 | (0A)000014 */ call void [mscorlib/*23000001*/]System.Runtime.CompilerServices.RuntimeHelpers/*01000015*/::InitializeArray(class [mscorlib/*23000001*/]System.Array/*01000016*/,
valuetype [mscorlib/*23000001*/]System.RuntimeFieldHandle/*01000017*/) /* 0A000014 */
IL_001a: /* 0A | */ stloc.0
//000008: // ...
//000009: }
IL_001b: /* 00 | */ nop
IL_001c: /* 2A | */ ret
} // end of method Class1::.ctor
The compiler created the struct <PrivateImplementationDetails>{975506E6-7C24-4C2B-8956-C1B9CF8B80C4}
with the field $$method0x6000001-1
for the initialization value and uses RuntimeHelpers.InitializeArray
in order to initialize the new array at runtime. The original values defined in C# seem to be stored in the field and get copied by using the field handle? But how are the values laid out?
There must be some better/easier way to read those constants from the assembly?
non response
What you are trying to do verge on the impossible (note that the single case in your example is probably doable, but probably wouldn't cover your full needs)
The <PrivateImplementationDetails>
is created by the C# compiler only in some cases (numeric arrays over a certain size, it seems). For all the other cases, direct initialization in the constructor is done. See http://goo.gl/iC6MRv for some examples.
Note that the IL code you are seeing isn't "written in the stone"... There are no rules that dictate to a C# compiler how it should create array initializers. For example Roslyn (the link I gave is generated by Roslyn) uses a PrivateImplementationDetails
instead of <PrivateImplementationDetails>{975506E6-7C24-4C2B-8956-C1B9CF8B80C4}
. And who knows what code is generated by the Mono compiler.
In the most general case it isn't possible know the values of an initialized array without executing the constructor (so instantiating the class) and taking a look at the obtained object. But this clearly has other problems (the initialization of a class could have side effects, or could require parameters)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With