示例#1
0
        /// <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);
            }
        }