diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AnonymousTypes.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AnonymousTypes.cs index 1c85f92f9b..32483e92cf 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AnonymousTypes.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AnonymousTypes.cs @@ -174,5 +174,18 @@ private static Action MakeAction(T template) { return null; } +#if ROSLYN + private static TValue GetOrCreate(TKey key, Func factory) + { + return factory(key, 1); + } + + private static int MixedLambdaParameters() + { + return GetOrCreate(new { + Value = 1 + }, (item, context) => item.Value + context); + } +#endif } } diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 398181075e..5656f1c2b9 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -2669,6 +2669,8 @@ IType GetTaskType(IType resultType) IEnumerable MakeParameters(IReadOnlyList parameters, ILFunction function) { var variables = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index!.Value); + var result = new List(parameters.Count); + bool anyAnonymousType = false; int i = 0; foreach (var parameter in parameters) { @@ -2684,10 +2686,21 @@ IEnumerable MakeParameters(IReadOnlyList param pd.Name = "P_" + i; } if (settings.AnonymousTypes && parameter.Type.ContainsAnonymousType()) - pd.Type = null; - yield return pd; + anyAnonymousType = true; + result.Add(pd); i++; } + // An anonymous type cannot be named, so a lambda with such a parameter must be implicitly typed. + // C# also requires all lambda parameters to use the same form (CS0748). Drop every type when the + // remaining parameter syntax permits it; otherwise keep the converted declarations as a + // best-effort fallback for an unrepresentable signature. + if (anyAnonymousType && result.All(p => p.ParameterModifier == ReferenceKind.None + && !p.IsParams && !p.IsScopedRef && p.Attributes.Count == 0 && p.DefaultExpression is null)) + { + foreach (var pd in result) + pd.Type = null; + } + return result; } protected internal override TranslatedExpression VisitBlockContainer(BlockContainer container, TranslationContext context)