// If binder is null, then get it from the compilation. Otherwise use the provided binder. // Don't always get it from the compilation because we might be in a speculative context (local function parameter), // in which case the declaring compilation is the wrong one. protected ConstantValue MakeDefaultExpression(DiagnosticBag diagnostics, Binder binder) { var parameterSyntax = this.CSharpSyntaxNode; if (parameterSyntax == null) { return(ConstantValue.NotAvailable); } var defaultSyntax = parameterSyntax.Default; if (defaultSyntax == null) { return(ConstantValue.NotAvailable); } if (binder == null) { var syntaxTree = _syntaxRef.SyntaxTree; var compilation = this.DeclaringCompilation; var binderFactory = compilation.GetBinderFactory(syntaxTree); binder = binderFactory.GetBinder(defaultSyntax); } Debug.Assert(binder.GetBinder(defaultSyntax) == null); Binder binderForDefault = binder.CreateBinderForParameterDefaultValue(this, defaultSyntax); Debug.Assert(binderForDefault.InParameterDefaultValue); Debug.Assert(binderForDefault.ContainingMemberOrLambda == ContainingSymbol); BoundExpression valueBeforeConversion; var convertedExpression = binderForDefault.BindParameterDefaultValue(defaultSyntax, parameterType, diagnostics, out valueBeforeConversion); bool hasErrors = ParameterHelpers.ReportDefaultParameterErrors(binder, ContainingSymbol, parameterSyntax, this, valueBeforeConversion, diagnostics); if (hasErrors) { return(ConstantValue.Bad); } // If we have something like M(double? x = 1) then the expression we'll get is (double?)1, which // does not have a constant value. The constant value we want is (double)1. if (convertedExpression.ConstantValue == null && convertedExpression.Kind == BoundKind.Conversion) { if (parameterType.IsNullableType()) { convertedExpression = binder.GenerateConversionForAssignment(parameterType.GetNullableUnderlyingType(), valueBeforeConversion, diagnostics, isDefaultParameter: true); } } // represent default(struct) by a Null constant: var value = convertedExpression.ConstantValue ?? ConstantValue.Null; VerifyParamDefaultValueMatchesAttributeIfAny(value, defaultSyntax.Value, diagnostics); return(value); }