static void CheckConversion (IMemberContext mc, MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, TypeSpec ttype, Location loc) { var expr = new EmptyExpression (atype); if (!Convert.ImplicitStandardConversionExists (expr, ttype)) { mc.Compiler.Report.SymbolRelatedToPreviousError (tparam); if (TypeManager.IsValueType (atype)) { mc.Compiler.Report.Error (315, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing conversion from `{0}' to `{3}'", atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ()); } else if (atype.IsGenericParameter) { mc.Compiler.Report.Error (314, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing or type parameter conversion from `{0}' to `{3}'", atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ()); } else { mc.Compiler.Report.Error (311, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no implicit reference conversion from `{0}' to `{3}'", atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ()); } } }
static bool CheckConstraint (IMemberContext mc, MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, Location loc) { // // First, check the `class' and `struct' constraints. // if (tparam.HasSpecialClass && !TypeManager.IsReferenceType (atype)) { mc.Compiler.Report.Error (452, loc, "The type `{0}' must be a reference type in order to use it as type parameter `{1}' in the generic type or method `{2}'", TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ()); return false; } if (tparam.HasSpecialStruct && (!TypeManager.IsValueType (atype) || TypeManager.IsNullableType (atype))) { mc.Compiler.Report.Error (453, loc, "The type `{0}' must be a non-nullable value type in order to use it as type parameter `{1}' in the generic type or method `{2}'", TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ()); return false; } // // The class constraint comes next. // if (tparam.HasTypeConstraint) { CheckConversion (mc, context, atype, tparam, tparam.BaseType, loc); } // // Now, check the interfaces and type parameters constraints // if (tparam.Interfaces != null) { if (TypeManager.IsNullableType (atype)) { mc.Compiler.Report.Error (313, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. The nullable type `{0}' never satisfies interface constraint", atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError ()); } else { foreach (TypeSpec iface in tparam.Interfaces) { CheckConversion (mc, context, atype, tparam, iface, loc); } } } // // Finally, check the constructor constraint. // if (!tparam.HasSpecialConstructor) return true; if (!HasDefaultConstructor (atype)) { mc.Compiler.Report.SymbolRelatedToPreviousError (atype); mc.Compiler.Report.Error (310, loc, "The type `{0}' must have a public parameterless constructor in order to use it as parameter `{1}' in the generic type or method `{2}'", TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ()); return false; } return true; }