/// <summary> /// Does an expression of type <paramref name="expressionType"/> "match" a pattern that looks for /// type <paramref name="patternType"/>? /// 'true' if the matched type catches all of them, 'false' if it catches none of them, and /// 'null' if it might catch some of them. For this test we assume the expression's value /// isn't null. /// </summary> protected bool?ExpressionOfTypeMatchesPatternType( TypeSymbol expressionType, TypeSymbol patternType, ref HashSet <DiagnosticInfo> useSiteDiagnostics) { if (expressionType == patternType) { return(true); } var conversion = _conversions.ClassifyBuiltInConversion(expressionType, patternType, ref useSiteDiagnostics); // This is for classification purposes only; we discard use-site diagnostics. Use-site diagnostics will // be given if a conversion is actually used. switch (conversion.Kind) { case ConversionKind.Boxing: // a value of type int matches a pattern of type object case ConversionKind.Identity: // a value of a given type matches a pattern of that type case ConversionKind.ImplicitReference: // a value of type string matches a pattern of type object return(true); case ConversionKind.ImplicitNullable: // a value of type int matches a pattern of type int? case ConversionKind.ExplicitNullable: // a non-null value of type "int?" matches a pattern of type int // but if the types differ (e.g. one of them is type byte and the other is type int?).. no match return(ConversionsBase.HasIdentityConversion(expressionType.StrippedType().TupleUnderlyingTypeOrSelf(), patternType.StrippedType().TupleUnderlyingTypeOrSelf())); case ConversionKind.ExplicitEnumeration: // a value of enum type does not match a pattern of integral type case ConversionKind.ExplicitNumeric: // a value of type long does not match a pattern of type int case ConversionKind.ImplicitNumeric: // a value of type short does not match a pattern of type int case ConversionKind.ImplicitTuple: // distinct tuple types don't match case ConversionKind.NoConversion: return(false); case ConversionKind.ExplicitDynamic: // a value of type dynamic might not match a pattern of type other than object case ConversionKind.ExplicitReference: // a narrowing reference conversion might or might not succeed case ConversionKind.Unboxing: // a value of type object might match a pattern of type int return(null); default: // other conversions don't apply (e.g. conversions from expression, user-defined) and should not arise throw ExceptionUtilities.UnexpectedValue(conversion.Kind); } }