// See NamedTypeSymbol.IsTupleCompatible. internal static bool IsTupleCompatible(this Type type, out int cardinality) { if (type.IsGenericType && AreNamesEqual(type.Namespace, "System") && type.Name.StartsWith(TupleTypeNamePrefix, StringComparison.Ordinal)) { var typeArguments = type.GetGenericArguments(); int n = typeArguments.Length; if ((n > 0) && (n <= TupleFieldRestPosition)) { if (!AreNamesEqual(type.Name, TupleTypeNamePrefix + n)) { cardinality = 0; return(false); } if (n < TupleFieldRestPosition) { cardinality = n; return(true); } var restType = typeArguments[n - 1]; int restCardinality; if (restType.IsTupleCompatible(out restCardinality)) { cardinality = n - 1 + restCardinality; return(true); } } } cardinality = 0; return(false); }
/// <summary> /// Returns type argument if the type is /// Nullable<T>, otherwise null. /// </summary> internal static Type GetNullableTypeArgument(this Type type) { if (type.IsMscorlibType("System", "Nullable`1")) { var typeArgs = type.GetGenericArguments(); if (typeArgs.Length == 1) { return(typeArgs[0]); } } return(null); }
/// <summary> /// Substitute references to type parameters from 'typeDef' /// with type arguments from 'typeArgs' in type 'type'. /// </summary> internal static Type Substitute(this Type type, Type typeDef, Type[] typeArgs) { Debug.Assert(typeDef.IsGenericTypeDefinition); Debug.Assert(typeDef.GetGenericArguments().Length == typeArgs.Length); if (type.IsGenericType) { var builder = ArrayBuilder <Type> .GetInstance(); foreach (var t in type.GetGenericArguments()) { builder.Add(t.Substitute(typeDef, typeArgs)); } var typeDefinition = type.GetGenericTypeDefinition(); return(typeDefinition.MakeGenericType(builder.ToArrayAndFree())); } else if (type.IsArray) { var elementType = type.GetElementType(); elementType = elementType.Substitute(typeDef, typeArgs); var n = type.GetArrayRank(); return((n == 1) ? elementType.MakeArrayType() : elementType.MakeArrayType(n)); } else if (type.IsPointer) { var elementType = type.GetElementType(); elementType = elementType.Substitute(typeDef, typeArgs); return(elementType.MakePointerType()); } else if (type.IsGenericParameter) { if (type.DeclaringType.Equals(typeDef)) { var ordinal = type.GenericParameterPosition; return(typeArgs[ordinal]); } } return(type); }