mirror of https://github.com/icsharpcode/ILSpy.git
10 changed files with 245 additions and 1 deletions
@ -0,0 +1,68 @@
@@ -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 @@
@@ -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