public override IType VisitParameterizedType(ParameterizedType type) { IType newType = base.VisitParameterizedType(type); if (newType != type && ConstraintsValid) { // something was changed, so we need to validate the constraints ParameterizedType newParameterizedType = newType as ParameterizedType; if (newParameterizedType != null) { // C# 4.0 spec: §4.4.4 Satisfying constraints var typeParameters = newParameterizedType.GetDefinition().TypeParameters; for (int i = 0; i < typeParameters.Count; i++) { ITypeParameter tp = typeParameters[i]; IType typeArg = newParameterizedType.TypeArguments[i]; if (tp.HasReferenceTypeConstraint) { if (typeArg.IsReferenceType(overloadResolution.context) != true) { ConstraintsValid = false; } } if (tp.HasValueTypeConstraint) { if (typeArg.IsReferenceType(overloadResolution.context) != false) { ConstraintsValid = false; } if (NullableType.IsNullable(typeArg)) { ConstraintsValid = false; } } if (tp.HasDefaultConstructorConstraint) { ITypeDefinition def = typeArg.GetDefinition(); if (def != null && def.IsAbstract) { ConstraintsValid = false; } ConstraintsValid &= typeArg.GetConstructors( overloadResolution.context, m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public ).Any(); } foreach (IType constraintType in tp.Constraints) { IType c = newParameterizedType.SubstituteInType(constraintType); ConstraintsValid &= overloadResolution.IsConstraintConvertible(typeArg, c); } } } } return(newType); }
public override IType VisitParameterizedType(ParameterizedType type) { IType newType = base.VisitParameterizedType(type); if (newType != type && ConstraintsValid) { // something was changed, so we need to validate the constraints ParameterizedType newParameterizedType = newType as ParameterizedType; if (newParameterizedType != null) { // C# 4.0 spec: §4.4.4 Satisfying constraints var typeParameters = newParameterizedType.GetDefinition().TypeParameters; for (int i = 0; i < typeParameters.Count; i++) { ITypeParameter tp = typeParameters[i]; IType typeArg = newParameterizedType.GetTypeArgument(i); switch (typeArg.Kind) // void, null, and pointers cannot be used as type arguments { case TypeKind.Void: case TypeKind.Null: case TypeKind.Pointer: ConstraintsValid = false; break; } if (tp.HasReferenceTypeConstraint) { if (typeArg.IsReferenceType(context) != true) { ConstraintsValid = false; } } if (tp.HasValueTypeConstraint) { if (!NullableType.IsNonNullableValueType(typeArg, context)) { ConstraintsValid = false; } } if (tp.HasDefaultConstructorConstraint) { ITypeDefinition def = typeArg.GetDefinition(); if (def != null && def.IsAbstract) { ConstraintsValid = false; } ConstraintsValid &= typeArg.GetConstructors( context, m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public, GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions ).Any(); } foreach (IType constraintType in tp.Constraints) { IType c = newParameterizedType.SubstituteInType(constraintType); ConstraintsValid &= conversions.IsConstraintConvertible(typeArg, c); } } } } return(newType); }