mirror of https://github.com/icsharpcode/ILSpy.git
10 changed files with 245 additions and 1 deletions
@ -0,0 +1,68 @@ |
|||||||
|
#pragma warning disable CS9099, CS9100
|
||||||
|
using System; |
||||||
|
using System.Reflection; |
||||||
|
|
||||||
|
namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness |
||||||
|
{ |
||||||
|
class LambdaOptionalAndParamsParameters |
||||||
|
{ |
||||||
|
static void Main() |
||||||
|
{ |
||||||
|
#if CS120 && !NET40
|
||||||
|
ReportMetadata(); |
||||||
|
ReportCalls(); |
||||||
|
#endif
|
||||||
|
} |
||||||
|
|
||||||
|
#if CS120 && !NET40
|
||||||
|
delegate int OptionalFunc(int x = 5); |
||||||
|
|
||||||
|
delegate int PlainFunc(int x); |
||||||
|
|
||||||
|
delegate void ParamsAction(params int[] xs); |
||||||
|
|
||||||
|
delegate void PlainAction(int[] xs); |
||||||
|
|
||||||
|
// A lambda's parameter list does not have to repeat what the delegate declares: it may
|
||||||
|
// state a different default, one the delegate does not have, or none where the delegate
|
||||||
|
// has one, and the same for the params modifier. Metadata records what the lambda itself
|
||||||
|
// declared, and reflection reports that rather than the delegate's, so the decompiled
|
||||||
|
// lambda has to carry the lambda's own list back.
|
||||||
|
static void Report(string name, Delegate d) |
||||||
|
{ |
||||||
|
ParameterInfo p = d.Method.GetParameters()[0]; |
||||||
|
Console.WriteLine("{0}: hasDefault={1} default={2} params={3}", |
||||||
|
name, |
||||||
|
p.HasDefaultValue, |
||||||
|
p.HasDefaultValue ? p.DefaultValue : "none", |
||||||
|
p.IsDefined(typeof(ParamArrayAttribute), inherit: false)); |
||||||
|
} |
||||||
|
|
||||||
|
static void ReportMetadata() |
||||||
|
{ |
||||||
|
Report("DefaultOnlyInDelegate", (OptionalFunc)((int x) => x * 2)); |
||||||
|
Report("DefaultOnlyInLambda", (PlainFunc)((int x = 3) => x * 2)); |
||||||
|
Report("DefaultDiffersFromDelegate", (OptionalFunc)((int x = 7) => x * 2)); |
||||||
|
Report("DefaultAgreesWithDelegate", (OptionalFunc)((int x = 5) => x * 2)); |
||||||
|
Report("ParamsOnlyInDelegate", (ParamsAction)((int[] xs) => Console.WriteLine(xs.Length))); |
||||||
|
Report("ParamsOnlyInLambda", (PlainAction)((params int[] xs) => Console.WriteLine(xs.Length))); |
||||||
|
} |
||||||
|
|
||||||
|
// The value a caller gets for an omitted argument comes from the delegate, never from the
|
||||||
|
// lambda, so these stay the same whatever the lambda declared.
|
||||||
|
static void ReportCalls() |
||||||
|
{ |
||||||
|
OptionalFunc noDefault = (int x) => x * 2; |
||||||
|
OptionalFunc otherDefault = (int x = 7) => x * 2; |
||||||
|
Console.WriteLine(noDefault()); |
||||||
|
Console.WriteLine(otherDefault()); |
||||||
|
Console.WriteLine(otherDefault(1)); |
||||||
|
|
||||||
|
ParamsAction expandedByDelegate = (int[] xs) => Console.WriteLine(xs.Length); |
||||||
|
expandedByDelegate(1, 2, 3); |
||||||
|
PlainAction notExpanded = (params int[] xs) => Console.WriteLine(xs.Length); |
||||||
|
notExpanded(new int[2]); |
||||||
|
} |
||||||
|
#endif
|
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,99 @@ |
|||||||
|
#pragma warning disable CS9099, CS9100
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty |
||||||
|
{ |
||||||
|
internal class LambdaOptionalAndParamsParameters |
||||||
|
{ |
||||||
|
public delegate void ParamsAction(params int[] xs); |
||||||
|
|
||||||
|
public delegate int OptionalFunc(int x = 5); |
||||||
|
|
||||||
|
public delegate int PlainFunc(int x); |
||||||
|
|
||||||
|
// A lambda states 'params' and defaults on its own account: what the delegate declares
|
||||||
|
// is the delegate's, and reflection over the lambda's method reports only the lambda's.
|
||||||
|
// Roslyn records the modifier on the anonymous function's method from version 5 on, so
|
||||||
|
// the cases that need it back are guarded on ROSLYN5.
|
||||||
|
|
||||||
|
private int total; |
||||||
|
|
||||||
|
#if ROSLYN5
|
||||||
|
public ParamsAction ParamsStatementBody() |
||||||
|
{ |
||||||
|
return (params int[] xs) => { |
||||||
|
total += xs.Length; |
||||||
|
Console.WriteLine(xs.Length); |
||||||
|
}; |
||||||
|
} |
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ROSLYN5
|
||||||
|
public ParamsAction ParamsSingleStatementBody() |
||||||
|
{ |
||||||
|
return (params int[] xs) => { |
||||||
|
Console.WriteLine(xs.Length); |
||||||
|
}; |
||||||
|
} |
||||||
|
#endif
|
||||||
|
|
||||||
|
public OptionalFunc OptionalStatementBody() |
||||||
|
{ |
||||||
|
return (int x = 5) => { |
||||||
|
total += x; |
||||||
|
return x * 2; |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
public OptionalFunc OptionalExpressionBody() |
||||||
|
{ |
||||||
|
return (int x = 5) => x * 2; |
||||||
|
} |
||||||
|
|
||||||
|
public ParamsAction ParamsWithoutParameterList() |
||||||
|
{ |
||||||
|
return delegate { |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
public OptionalFunc OptionalWithoutParameterList() |
||||||
|
{ |
||||||
|
return delegate { |
||||||
|
return 1; |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
// The lambda's own defaults and params modifier can differ from the delegate's; the metadata
|
||||||
|
// records the lambda's, so that is what must round-trip.
|
||||||
|
public OptionalFunc OptionalDifferentDefault() |
||||||
|
{ |
||||||
|
return (int x = 7) => x * 2; |
||||||
|
} |
||||||
|
|
||||||
|
public OptionalFunc OptionalOnlyInDelegate() |
||||||
|
{ |
||||||
|
return (int x) => x * 2; |
||||||
|
} |
||||||
|
|
||||||
|
public PlainFunc OptionalOnlyInLambda() |
||||||
|
{ |
||||||
|
return (int x = 3) => x * 2; |
||||||
|
} |
||||||
|
|
||||||
|
public ParamsAction ParamsOnlyInDelegate() |
||||||
|
{ |
||||||
|
return (int[] xs) => { |
||||||
|
Console.WriteLine(xs.Length); |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
#if ROSLYN5
|
||||||
|
public Action<int[]> ParamsOnlyInLambda() |
||||||
|
{ |
||||||
|
return (params int[] xs) => { |
||||||
|
Console.WriteLine(xs.Length); |
||||||
|
}; |
||||||
|
} |
||||||
|
#endif
|
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue