2 // generic.cs: Support classes for generics
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2003 Ximian, Inc.
10 using System.Reflection;
11 using System.Reflection.Emit;
12 using System.Globalization;
13 using System.Collections;
16 namespace Mono.CSharp {
18 public enum SpecialConstraint
26 // Tracks the constraints for a type parameter
28 public class Constraints : GenericConstraints {
30 ArrayList constraints;
34 // name is the identifier, constraints is an arraylist of
35 // Expressions (with types) or `true' for the constructor constraint.
37 public Constraints (string name, ArrayList constraints,
41 this.constraints = constraints;
45 public string TypeParameter {
51 bool has_ctor_constraint;
52 bool has_reference_type;
54 TypeExpr class_constraint;
55 ArrayList iface_constraints;
56 ArrayList type_param_constraints;
57 int num_constraints, first_constraint;
58 Type class_constraint_type;
59 Type[] iface_constraint_types;
61 public bool HasConstructorConstraint {
62 get { return has_ctor_constraint; }
65 public bool Resolve (DeclSpace ds)
67 iface_constraints = new ArrayList ();
68 type_param_constraints = new ArrayList ();
70 foreach (object obj in constraints) {
71 if (has_ctor_constraint) {
72 Report.Error (401, loc,
73 "The new() constraint must be last.");
77 if (obj is SpecialConstraint) {
78 SpecialConstraint sc = (SpecialConstraint) obj;
80 if (sc == SpecialConstraint.Constructor) {
81 if (!has_value_type) {
82 has_ctor_constraint = true;
87 451, loc, "The new () constraint " +
88 "cannot be used with the `struct' " +
93 if ((num_constraints > 0) || has_reference_type ||
95 Report.Error (449, loc,
96 "The `class' or `struct' " +
97 "constraint must be first");
101 if (sc == SpecialConstraint.ReferenceType)
102 has_reference_type = true;
104 has_value_type = true;
108 TypeExpr expr = ds.ResolveTypeExpr ((Expression) obj, false, loc);
112 TypeParameterExpr texpr = expr as TypeParameterExpr;
114 type_param_constraints.Add (expr);
115 else if (expr.IsInterface)
116 iface_constraints.Add (expr);
117 else if (class_constraint != null) {
118 Report.Error (406, loc,
119 "`{0}': the class constraint for `{1}' " +
120 "must come before any other constraints.",
123 } else if (has_reference_type || has_value_type) {
124 Report.Error (450, loc, "`{0}': cannot specify both " +
125 "a constraint class and the `class' " +
126 "or `struct' constraint.", expr.Name);
129 class_constraint = expr;
137 bool CheckTypeParameterConstraints (TypeParameter tparam, Hashtable seen)
139 seen.Add (tparam, true);
141 Constraints constraints = tparam.Constraints;
142 if (constraints == null)
145 if (constraints.IsValueType) {
146 Report.Error (456, loc, "Type parameter `{0}' has " +
147 "the `struct' constraint, so it cannot " +
148 "be used as a constraint for `{1}'",
153 if (constraints.type_param_constraints == null)
156 foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
157 if (seen.Contains (expr.TypeParameter)) {
158 Report.Error (454, loc, "Circular constraint " +
159 "dependency involving `{0}' and `{1}'",
160 tparam.Name, expr.Name);
164 if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
171 public bool ResolveTypes (EmitContext ec)
173 foreach (TypeParameterExpr expr in type_param_constraints) {
174 Hashtable seen = new Hashtable ();
175 if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
179 ArrayList list = new ArrayList ();
181 foreach (TypeExpr iface_constraint in iface_constraints) {
182 Type resolved = iface_constraint.ResolveType (ec);
183 if (resolved == null)
186 foreach (Type type in list) {
187 if (!type.Equals (resolved))
190 Report.Error (405, loc,
191 "Duplicate constraint `{0}' for type " +
192 "parameter `{1}'.", resolved, name);
199 foreach (TypeParameterExpr expr in type_param_constraints) {
200 Type resolved = expr.ResolveType (ec);
201 if (resolved == null)
204 foreach (Type type in list) {
205 if (!type.Equals (resolved))
208 Report.Error (405, loc,
209 "Duplicate constraint `{0}' for type " +
210 "parameter `{1}'.", resolved, name);
217 iface_constraint_types = new Type [list.Count];
218 list.CopyTo (iface_constraint_types, 0);
220 if (class_constraint != null) {
221 class_constraint_type = class_constraint.ResolveType (ec);
222 if (class_constraint_type == null)
225 if (class_constraint_type.IsSealed) {
226 Report.Error (701, loc,
227 "`{0}' is not a valid bound. Bounds " +
228 "must be interfaces or non sealed " +
229 "classes", class_constraint_type);
233 if ((class_constraint_type == TypeManager.array_type) ||
234 (class_constraint_type == TypeManager.delegate_type) ||
235 (class_constraint_type == TypeManager.enum_type) ||
236 (class_constraint_type == TypeManager.value_type) ||
237 (class_constraint_type == TypeManager.object_type)) {
238 Report.Error (702, loc,
239 "Bound cannot be special class `{0}'",
240 class_constraint_type);
245 if (has_reference_type)
246 class_constraint_type = TypeManager.object_type;
247 else if (has_value_type)
248 class_constraint_type = TypeManager.value_type;
253 public bool CheckDependencies (EmitContext ec)
255 foreach (TypeParameterExpr expr in type_param_constraints) {
256 if (!CheckDependencies (expr.TypeParameter, ec))
263 bool CheckDependencies (TypeParameter tparam, EmitContext ec)
265 Constraints constraints = tparam.Constraints;
266 if (constraints == null)
269 if (IsValueType && constraints.HasClassConstraint) {
270 Report.Error (455, loc, "Type parameter `{0}' inherits " +
271 "conflicting constraints `{1}' and `{2}'",
272 name, constraints.ClassConstraint,
277 if (HasClassConstraint && constraints.HasClassConstraint) {
278 Type t1 = ClassConstraint;
279 TypeExpr e1 = class_constraint;
280 Type t2 = constraints.ClassConstraint;
281 TypeExpr e2 = constraints.class_constraint;
283 if (!Convert.ImplicitReferenceConversionExists (e1, t2) &&
284 !Convert.ImplicitReferenceConversionExists (e2, t1)) {
285 Report.Error (455, loc,
286 "Type parameter `{0}' inherits " +
287 "conflicting constraints `{1}' and `{2}'",
293 if (constraints.type_param_constraints == null)
296 foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
297 if (!CheckDependencies (expr.TypeParameter, ec))
304 public void Define (GenericTypeParameterBuilder type)
306 if (has_ctor_constraint)
307 type.Mono_SetConstructorConstraint ();
308 if (has_reference_type)
309 type.Mono_SetReferenceTypeConstraint ();
310 else if (has_value_type)
311 type.Mono_SetValueTypeConstraint ();
314 public bool HasConstructor {
315 get { return has_ctor_constraint; }
318 public bool IsReferenceType {
319 get { return has_reference_type; }
322 public bool IsValueType {
323 get { return has_value_type; }
326 public bool HasClassConstraint {
327 get { return class_constraint_type != null; }
330 public Type ClassConstraint {
331 get { return class_constraint_type; }
334 public Type[] InterfaceConstraints {
335 get { return iface_constraint_types; }
338 internal bool IsSubclassOf (Type t)
340 if ((class_constraint_type != null) &&
341 class_constraint_type.IsSubclassOf (t))
344 if (iface_constraint_types == null)
347 foreach (Type iface in iface_constraint_types) {
348 if (TypeManager.IsSubclassOf (iface, t))
355 public bool CheckInterfaceMethod (EmitContext ec, GenericConstraints gc)
357 if (!ResolveTypes (ec))
360 if (gc.HasConstructor != HasConstructor)
362 if (gc.IsReferenceType != IsReferenceType)
364 if (gc.IsValueType != IsValueType)
366 if (gc.HasClassConstraint != HasClassConstraint)
369 if (HasClassConstraint && !gc.ClassConstraint.Equals (ClassConstraint))
372 int gc_icount = gc.InterfaceConstraints != null ?
373 gc.InterfaceConstraints.Length : 0;
374 int icount = InterfaceConstraints != null ?
375 InterfaceConstraints.Length : 0;
377 if (gc_icount != icount)
380 foreach (Type iface in gc.InterfaceConstraints) {
382 foreach (Type check in InterfaceConstraints) {
383 if (iface.Equals (check)) {
398 // This type represents a generic type parameter
400 public class TypeParameter : IMemberContainer {
402 Constraints constraints;
404 GenericTypeParameterBuilder type;
406 public TypeParameter (string name, Constraints constraints, Location loc)
409 this.constraints = constraints;
419 public Location Location {
425 public Constraints Constraints {
431 public bool HasConstructorConstraint {
433 if (constraints != null)
434 return constraints.HasConstructorConstraint;
446 public bool Resolve (DeclSpace ds)
448 if (constraints != null)
449 return constraints.Resolve (ds);
454 public void Define (GenericTypeParameterBuilder type)
457 Type[] ifaces = null;
458 if (constraints != null)
459 constraints.Define (type);
460 TypeManager.AddTypeParameter (type, this);
463 public bool DefineType (EmitContext ec)
465 return DefineType (ec, null, null, false);
468 public bool DefineType (EmitContext ec, MethodBuilder builder,
469 MethodInfo implementing, bool is_override)
471 GenericConstraints gc;
473 if (implementing != null) {
474 if (is_override && (constraints != null)) {
476 460, loc, "Constraints for override and " +
477 "explicit interface implementation methods " +
478 "are inherited from the base method so they " +
479 "cannot be specified directly");
483 MethodBase mb = implementing;
484 if (mb.Mono_IsInflatedMethod)
485 mb = mb.GetGenericMethodDefinition ();
487 int pos = type.GenericParameterPosition;
488 ParameterData pd = Invocation.GetParameterData (mb);
489 gc = pd.GenericConstraints (pos);
490 Type mparam = mb.GetGenericArguments () [pos];
492 if (((constraints != null) && (gc == null)) ||
493 ((constraints == null) && (gc != null)) ||
494 ((constraints != null) &&
495 !constraints.CheckInterfaceMethod (ec, gc))) {
496 Report.SymbolRelatedToPreviousError (implementing);
499 425, loc, "The constraints for type " +
500 "parameter `{0}' of method `{1}' must match " +
501 "the constraints for type parameter `{2}' " +
502 "of interface method `{3}'. Consider using " +
503 "an explicit interface implementation instead",
504 Name, TypeManager.CSharpSignature (builder),
505 mparam, TypeManager.CSharpSignature (mb));
509 if (constraints != null) {
510 if (!constraints.ResolveTypes (ec))
514 gc = (GenericConstraints) constraints;
520 if (gc.HasClassConstraint)
521 type.SetBaseTypeConstraint (gc.ClassConstraint);
523 type.SetInterfaceConstraints (gc.InterfaceConstraints);
524 TypeManager.RegisterBuilder (type, gc.InterfaceConstraints);
529 public bool CheckDependencies (EmitContext ec)
531 if (constraints != null)
532 return constraints.CheckDependencies (ec);
541 IMemberContainer IMemberContainer.ParentContainer {
545 bool IMemberContainer.IsInterface {
549 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
551 return FindMembers (mt, bf, null, null);
554 MemberCache IMemberContainer.MemberCache {
558 public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
559 MemberFilter filter, object criteria)
561 if (constraints == null)
562 return MemberList.Empty;
564 ArrayList members = new ArrayList ();
566 GenericConstraints gc = (GenericConstraints) constraints;
568 if (gc.HasClassConstraint) {
569 MemberList list = TypeManager.FindMembers (
570 gc.ClassConstraint, mt, bf, filter, criteria);
572 members.AddRange (list);
575 foreach (Type t in gc.InterfaceConstraints) {
576 MemberList list = TypeManager.FindMembers (
577 t, mt, bf, filter, criteria);
579 members.AddRange (list);
582 return new MemberList (members);
585 public bool IsSubclassOf (Type t)
590 if (constraints != null)
591 return constraints.IsSubclassOf (t);
596 public override string ToString ()
598 return "TypeParameter[" + name + "]";
603 // This type represents a generic type parameter reference.
605 // These expressions are born in a fully resolved state.
607 public class TypeParameterExpr : TypeExpr {
608 TypeParameter type_parameter;
610 public override string Name {
612 return type_parameter.Name;
616 public TypeParameter TypeParameter {
618 return type_parameter;
622 public TypeParameterExpr (TypeParameter type_parameter, Location loc)
624 this.type_parameter = type_parameter;
628 public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
630 type = type_parameter.Type;
635 public override bool IsInterface {
636 get { return false; }
639 public void Error_CannotUseAsUnmanagedType (Location loc)
641 Report.Error (-203, loc, "Can not use type parameter as unamanged type");
645 public class TypeArguments {
646 public readonly Location Location;
653 public TypeArguments (Location loc)
655 args = new ArrayList ();
659 public TypeArguments (int dimension, Location loc)
661 this.dimension = dimension;
665 public void Add (Expression type)
668 throw new InvalidOperationException ();
673 public void Add (TypeArguments new_args)
676 throw new InvalidOperationException ();
678 args.AddRange (new_args.args);
681 public string[] GetDeclarations ()
683 string[] ret = new string [args.Count];
684 for (int i = 0; i < args.Count; i++) {
685 SimpleName sn = args [i] as SimpleName;
691 Report.Error (81, Location, "Type parameter declaration " +
692 "must be an identifier not a type");
698 public Type[] Arguments {
704 public bool HasTypeArguments {
706 return has_type_args;
719 public bool IsUnbound {
721 return dimension > 0;
725 public override string ToString ()
727 StringBuilder s = new StringBuilder ();
730 for (int i = 0; i < count; i++){
732 // FIXME: Use TypeManager.CSharpname once we have the type
735 s.Append (args [i].ToString ());
739 return s.ToString ();
742 public bool Resolve (EmitContext ec)
744 DeclSpace ds = ec.DeclSpace;
745 int count = args.Count;
748 atypes = new Type [count];
750 for (int i = 0; i < count; i++){
751 TypeExpr te = ds.ResolveTypeExpr (
752 (Expression) args [i], false, Location);
757 if (te is TypeParameterExpr)
758 has_type_args = true;
759 atypes [i] = te.ResolveType (ec);
761 if (atypes [i] == null) {
762 Report.Error (246, Location, "Cannot find type `{0}'",
771 public class ConstructedType : TypeExpr {
772 string name, full_name;
774 Type[] gen_params, atypes;
777 public ConstructedType (string name, TypeArguments args, Location l)
780 this.name = MemberName.MakeName (name, args.Count);
783 eclass = ExprClass.Type;
784 full_name = name + "<" + args.ToString () + ">";
787 public ConstructedType (string name, TypeParameter[] type_params, Location l)
788 : this (type_params, l)
793 full_name = name + "<" + args.ToString () + ">";
796 protected ConstructedType (TypeArguments args, Location l)
801 eclass = ExprClass.Type;
804 protected ConstructedType (TypeParameter[] type_params, Location l)
808 args = new TypeArguments (l);
809 foreach (TypeParameter type_param in type_params)
810 args.Add (new TypeParameterExpr (type_param, l));
812 eclass = ExprClass.Type;
815 public ConstructedType (Type t, TypeParameter[] type_params, Location l)
816 : this (type_params, l)
818 gt = t.GetGenericTypeDefinition ();
820 this.name = gt.FullName;
821 full_name = gt.FullName + "<" + args.ToString () + ">";
824 public ConstructedType (Type t, TypeArguments args, Location l)
827 gt = t.GetGenericTypeDefinition ();
829 this.name = gt.FullName;
830 full_name = gt.FullName + "<" + args.ToString () + ">";
833 public TypeArguments TypeArguments {
837 protected string DeclarationName {
839 StringBuilder sb = new StringBuilder ();
840 sb.Append (gt.FullName);
842 for (int i = 0; i < gen_params.Length; i++) {
845 sb.Append (gen_params [i]);
848 return sb.ToString ();
852 protected bool CheckConstraint (EmitContext ec, Type ptype, Expression expr,
855 if (TypeManager.HasGenericArguments (ctype)) {
856 Type[] types = TypeManager.GetTypeArguments (ctype);
858 TypeArguments new_args = new TypeArguments (loc);
860 for (int i = 0; i < types.Length; i++) {
863 if (t.IsGenericParameter) {
864 int pos = t.GenericParameterPosition;
865 t = args.Arguments [pos];
867 new_args.Add (new TypeExpression (t, loc));
870 ctype = new ConstructedType (ctype, new_args, loc).ResolveType (ec);
875 return Convert.ImplicitStandardConversionExists (expr, ctype);
878 protected bool CheckConstraints (EmitContext ec, int index)
880 Type atype = atypes [index];
881 Type ptype = gen_params [index];
886 Expression aexpr = new EmptyExpression (atype);
888 Type parent = ptype.BaseType;
891 // First, check the `class' and `struct' constraints.
893 if (parent == TypeManager.object_type) {
894 if (!atype.IsClass) {
895 Report.Error (452, loc, "The type `{0}' must be " +
896 "a reference type in order to use it " +
897 "as type parameter `{1}' in the " +
898 "generic type or method `{2}'.",
899 atype, ptype, DeclarationName);
902 } else if (parent == TypeManager.value_type) {
903 if (!atype.IsValueType) {
904 Report.Error (453, loc, "The type `{0}' must be " +
905 "a value type in order to use it " +
906 "as type parameter `{1}' in the " +
907 "generic type or method `{2}'.",
908 atype, ptype, DeclarationName);
914 // The class constraint comes next.
916 if ((parent != null) && (parent != TypeManager.object_type)) {
917 if (!CheckConstraint (ec, ptype, aexpr, parent)) {
918 Report.Error (309, loc, "The type `{0}' must be " +
919 "convertible to `{1}' in order to " +
920 "use it as parameter `{2}' in the " +
921 "generic type or method `{3}'",
922 atype, parent, ptype, DeclarationName);
928 // Now, check the interface constraints.
930 foreach (Type it in TypeManager.GetInterfaces (ptype)) {
932 if (it.IsGenericParameter)
933 itype = atypes [it.GenericParameterPosition];
937 if (!CheckConstraint (ec, ptype, aexpr, itype)) {
938 Report.Error (309, loc, "The type `{0}' must be " +
939 "convertible to `{1}' in order to " +
940 "use it as parameter `{2}' in the " +
941 "generic type or method `{3}'",
942 atype, itype, ptype, DeclarationName);
948 // Finally, check the constructor constraint.
951 if (!TypeManager.HasConstructorConstraint (ptype))
954 MethodGroupExpr mg = Expression.MemberLookup (
955 ec, atype, ".ctor", MemberTypes.Constructor,
956 BindingFlags.Public | BindingFlags.Instance |
957 BindingFlags.DeclaredOnly, loc)
960 if (atype.IsAbstract || (mg == null) || !mg.IsInstance) {
961 Report.Error (310, loc, "The type `{0}' must have a public " +
962 "parameterless constructor in order to use it " +
963 "as parameter `{1}' in the generic type or " +
964 "method `{2}'", atype, ptype, DeclarationName);
971 public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
977 // First, resolve the generic type.
980 Type nested = ec.DeclSpace.FindNestedType (loc, name, out ds);
981 if (nested != null) {
982 gt = nested.GetGenericTypeDefinition ();
984 TypeArguments new_args = new TypeArguments (loc);
985 foreach (TypeParameter param in ds.TypeParameters)
986 new_args.Add (new TypeParameterExpr (param, loc));
996 SimpleName sn = new SimpleName (name, loc);
997 TypeExpr resolved = sn.ResolveAsTypeTerminal (ec);
998 if ((resolved == null) || (resolved.Type == null)) {
999 Report.Error (246, loc,
1000 "The type or namespace name `{0}<...>' "+
1001 "could not be found", Basename);
1007 Report.Error (246, loc, "Cannot find type `{0}'<...>",
1012 num_args = TypeManager.GetNumberOfTypeArguments (t);
1013 if (num_args == 0) {
1014 Report.Error (308, loc,
1015 "The non-generic type `{0}' cannot " +
1016 "be used with type arguments.",
1017 TypeManager.CSharpName (t));
1021 gt = t.GetGenericTypeDefinition ();
1025 public override Type ResolveType (EmitContext ec)
1029 if (DoResolveAsTypeStep (ec) == null)
1033 // Resolve the arguments.
1035 if (args.Resolve (ec) == false)
1038 gen_params = gt.GetGenericArguments ();
1039 atypes = args.Arguments;
1041 if (atypes.Length != gen_params.Length) {
1042 Report.Error (305, loc,
1043 "Using the generic type `{0}' " +
1044 "requires {1} type arguments",
1045 TypeManager.GetFullName (gt),
1050 for (int i = 0; i < gen_params.Length; i++) {
1051 if (!CheckConstraints (ec, i))
1056 // Now bind the parameters.
1058 type = gt.BindGenericParameters (atypes);
1062 public Expression GetSimpleName (EmitContext ec)
1064 return new SimpleName (Basename, args, loc);
1067 public override bool CheckAccessLevel (DeclSpace ds)
1069 return ds.CheckAccessLevel (gt);
1072 public override bool AsAccessible (DeclSpace ds, int flags)
1074 return ds.AsAccessible (gt, flags);
1077 public override bool IsClass {
1078 get { return gt.IsClass; }
1081 public override bool IsValueType {
1082 get { return gt.IsValueType; }
1085 public override bool IsInterface {
1086 get { return gt.IsInterface; }
1089 public override bool IsSealed {
1090 get { return gt.IsSealed; }
1093 public override bool IsAttribute {
1094 get { return false; }
1097 public override bool Equals (object obj)
1099 ConstructedType cobj = obj as ConstructedType;
1103 if ((type == null) || (cobj.type == null))
1106 return type == cobj.type;
1109 public string Basename {
1111 int pos = name.LastIndexOf ('`');
1113 return name.Substring (0, pos);
1119 public override string Name {
1126 public class GenericMethod : DeclSpace
1128 public GenericMethod (NamespaceEntry ns, TypeContainer parent,
1129 MemberName name, Location l)
1130 : base (ns, parent, name, null, l)
1133 public override TypeBuilder DefineType ()
1135 throw new Exception ();
1138 public override bool Define ()
1140 for (int i = 0; i < TypeParameters.Length; i++)
1141 if (!TypeParameters [i].Resolve (Parent))
1147 public bool Define (MethodBuilder mb)
1152 GenericTypeParameterBuilder[] gen_params;
1153 string[] names = MemberName.TypeArguments.GetDeclarations ();
1154 gen_params = mb.DefineGenericParameters (names);
1155 for (int i = 0; i < TypeParameters.Length; i++)
1156 TypeParameters [i].Define (gen_params [i]);
1161 public bool DefineType (EmitContext ec, MethodBuilder mb,
1162 MethodInfo implementing, bool is_override)
1164 for (int i = 0; i < TypeParameters.Length; i++)
1165 if (!TypeParameters [i].DefineType (
1166 ec, mb, implementing, is_override))
1172 public override bool DefineMembers (TypeContainer parent)
1177 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1178 MemberFilter filter, object criteria)
1180 throw new Exception ();
1183 public override MemberCache MemberCache {
1185 throw new Exception ();
1189 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
1194 protected override void VerifyObsoleteAttribute()
1199 public override AttributeTargets AttributeTargets {
1201 return AttributeTargets.Method | AttributeTargets.ReturnValue;
1206 public class DefaultValueExpression : Expression
1209 LocalTemporary temp_storage;
1211 public DefaultValueExpression (Expression expr, Location loc)
1217 public override Expression DoResolve (EmitContext ec)
1219 type = ec.DeclSpace.ResolveType (expr, false, loc);
1223 if (type.IsGenericParameter || TypeManager.IsValueType (type))
1224 temp_storage = new LocalTemporary (ec, type);
1226 eclass = ExprClass.Variable;
1230 public override void Emit (EmitContext ec)
1232 if (temp_storage != null) {
1233 temp_storage.AddressOf (ec, AddressOp.LoadStore);
1234 ec.ig.Emit (OpCodes.Initobj, type);
1235 temp_storage.Emit (ec);
1237 ec.ig.Emit (OpCodes.Ldnull);