Merge pull request #3522 from henricm/fix-csharp-compiler-path-windows
[mono.git] / mcs / class / referencesource / mscorlib / system / typedreference.cs
1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 namespace System {
7
8     // TypedReference is basically only ever seen on the call stack, and in param arrays.
9     //  These are blob that must be dealt with by the compiler.
10     using System;
11     using System.Reflection;
12     using System.Runtime.CompilerServices;
13     using CultureInfo = System.Globalization.CultureInfo;
14     using FieldInfo = System.Reflection.FieldInfo;
15     using System.Security.Permissions;
16     using System.Runtime.Versioning;
17     using System.Diagnostics.Contracts;
18
19     [CLSCompliant(false)] 
20     [System.Runtime.InteropServices.ComVisible(true)]
21     [System.Runtime.Versioning.NonVersionable] // This only applies to field layout
22     public struct TypedReference
23     {
24 #if MONO
25 #pragma warning disable 169
26         RuntimeTypeHandle type;
27 #pragma warning restore
28 #endif
29         private IntPtr Value;
30         private IntPtr Type;
31
32         [System.Security.SecurityCritical]  // auto-generated_required
33         [CLSCompliant(false)]
34         public static TypedReference MakeTypedReference(Object target, FieldInfo[] flds) {
35             if (target == null)
36                 throw new ArgumentNullException("target");
37             if (flds == null)
38                 throw new ArgumentNullException("flds");
39             Contract.EndContractBlock();
40             if (flds.Length == 0)
41                 throw new ArgumentException(Environment.GetResourceString("Arg_ArrayZeroError"));
42
43             IntPtr[] fields = new IntPtr[flds.Length];
44             // For proper handling of Nullable<T> don't change GetType() to something like 'IsAssignableFrom'
45             // Currently we can't make a TypedReference to fields of Nullable<T>, which is fine.  
46             RuntimeType targetType = (RuntimeType)target.GetType();
47             for (int i = 0; i < flds.Length; i++)
48             {
49                 RuntimeFieldInfo field = flds[i] as RuntimeFieldInfo;
50                 if (field == null)
51                     throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeFieldInfo"));
52
53                 if (field.IsInitOnly || field.IsStatic)
54                     throw new ArgumentException(Environment.GetResourceString("Argument_TypedReferenceInvalidField"));
55                 
56                 if (targetType != field.GetDeclaringTypeInternal() && !targetType.IsSubclassOf(field.GetDeclaringTypeInternal()))
57                     throw new MissingMemberException(Environment.GetResourceString("MissingMemberTypeRef"));
58
59                 RuntimeType fieldType = (RuntimeType)field.FieldType;
60                 if (fieldType.IsPrimitive)
61                     throw new ArgumentException(Environment.GetResourceString("Arg_TypeRefPrimitve"));
62                 
63                 if (i < (flds.Length - 1) && !fieldType.IsValueType)
64                     throw new MissingMemberException(Environment.GetResourceString("MissingMemberNestErr"));
65                 
66                 fields[i] = field.FieldHandle.Value;
67                 targetType = fieldType;
68             }
69
70 #if MONO
71             return MakeTypedReferenceInternal (target, flds);
72 #else
73             TypedReference result = new TypedReference ();
74
75             // reference to TypedReference is banned, so have to pass result as pointer
76             unsafe 
77             {
78                 InternalMakeTypedReference(&result, target, fields, targetType);
79             }
80             return result;
81 #endif
82         }
83
84         [System.Security.SecurityCritical]  // auto-generated
85         [ResourceExposure(ResourceScope.None)]
86         [MethodImplAttribute(MethodImplOptions.InternalCall)]
87 #if MONO
88         extern static TypedReference MakeTypedReferenceInternal (object target, FieldInfo[] fields);
89 #else
90         // reference to TypedReference is banned, so have to pass result as pointer
91         private unsafe static extern void InternalMakeTypedReference(void* result, Object target, IntPtr[] flds, RuntimeType lastFieldType);
92 #endif
93         public override int GetHashCode()
94         {
95             if (Type == IntPtr.Zero)
96                 return 0;
97             else
98                 return __reftype(this).GetHashCode();
99         }
100
101         public override bool Equals(Object o)
102         {
103             throw new NotSupportedException(Environment.GetResourceString("NotSupported_NYI"));
104         }
105
106         [System.Security.SecuritySafeCritical]  // auto-generated
107         public unsafe static Object ToObject(TypedReference value)
108         {
109             return InternalToObject(&value);
110         }
111
112         [System.Security.SecurityCritical]  // auto-generated
113         [ResourceExposure(ResourceScope.None)]
114         [MethodImplAttribute(MethodImplOptions.InternalCall)]
115         internal unsafe extern static Object InternalToObject(void * value);
116
117         internal bool IsNull 
118         { 
119             get
120             {
121                 return Value.IsNull() && Type.IsNull(); 
122             }
123         }
124
125         public static Type GetTargetType (TypedReference value)
126         {
127             return __reftype(value);
128         }
129
130         public static RuntimeTypeHandle TargetTypeToken (TypedReference value)
131         {
132             return __reftype(value).TypeHandle;
133         }
134
135         //  This may cause the type to be changed.
136         [System.Security.SecuritySafeCritical]  // auto-generated
137         [CLSCompliant(false)]
138         public unsafe static void SetTypedReference(TypedReference target, Object value)
139         {
140 #if MONO
141             throw new NotImplementedException ("SetTypedReference");
142 #else
143             InternalSetTypedReference(&target, value);
144 #endif
145         }
146 #if !MONO
147         [System.Security.SecurityCritical]  // auto-generated
148         [ResourceExposure(ResourceScope.None)]
149         [MethodImplAttribute(MethodImplOptions.InternalCall)]
150         internal unsafe extern static void InternalSetTypedReference(void * target, Object value);
151 #endif
152     }
153
154 }