Skip to content

Commit 5319969

Browse files
Extend UseLambdaSyntax to emit statement lambdas
Under UseLambdaSyntax, anonymous functions became lambdas only when an expression body was possible; statement-bodied ones kept C# 2 delegate syntax. Now every anonymous function whose parameter shape a lambda can express uses lambda syntax; delegate syntax remains for ref/out/in and params parameters and for pre-C# 3 language profiles. Two latent issues surfaced by the wider lambda coverage: DeclareVariables assumed an insertion point directly under a LambdaExpression is an expression body it must convert to a block, which block-bodied lambdas now violate; and anonymous methods declared without a parameter list carry compiler-generated parameter names like '<p0>' that are not valid identifiers, so the lambda's mandatory parameter list regenerates such names from the parameter type: (object obj, EventArgs e) => ... A side effect visible in fixtures: an explicit parameter list can make a delegate-creation cast redundant that bare 'delegate' syntax needed for overload resolution, e.g. new Thread((ThreadStart)delegate { }) becomes new Thread(() => { }). Assisted-by: Claude:claude-fable-5:Claude Code
1 parent 51e662d commit 5319969

18 files changed

Lines changed: 83 additions & 62 deletions

ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1038.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
44
{
55
public class Issue1038<TK, TR> where TR : class, new()
66
{
7-
public event Action<TK, TR> TestEvent = delegate {
7+
public event Action<TK, TR> TestEvent = (TK A_0, TR A_1) => {
88
};
99
}
1010
}

ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ public static Func<Task<int>> AsyncLambda()
524524

525525
public static Func<Task<int>> AsyncDelegate()
526526
{
527-
return async delegate {
527+
return async () => {
528528
await Task.Delay(10);
529529
return 2;
530530
};

ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomTaskType.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public static Func<ValueTask<int>> AsyncLambda()
119119

120120
public static Func<ValueTask<int>> AsyncDelegate()
121121
{
122-
return async delegate {
122+
return async () => {
123123
await Task.Delay(10);
124124
return 2;
125125
};

ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,14 @@ public struct SomeData
5858

5959
public Action CaptureOfThis()
6060
{
61-
return delegate {
61+
return () => {
6262
CaptureOfThis();
6363
};
6464
}
6565

6666
public Action CaptureOfThisAndParameter(int a)
6767
{
68-
return delegate {
68+
return () => {
6969
CaptureOfThisAndParameter(a);
7070
};
7171
}
@@ -76,7 +76,7 @@ public Action CaptureOfThisAndParameterInForEach(int a)
7676
{
7777
if (item > 0)
7878
{
79-
return delegate {
79+
return () => {
8080
CaptureOfThisAndParameter(item + a);
8181
};
8282
}
@@ -91,7 +91,7 @@ public Action CaptureOfThisAndParameterInForEachWithItemCopy(int a)
9191
int copyOfItem = item;
9292
if (item > 0)
9393
{
94-
return delegate {
94+
return () => {
9595
CaptureOfThisAndParameter(item + a + copyOfItem);
9696
};
9797
}
@@ -118,18 +118,18 @@ public void Bar(Func<int> f)
118118

119119
private void Bug955()
120120
{
121-
new Thread((ThreadStart)delegate {
121+
new Thread(() => {
122122
});
123123
}
124124

125125
public void Bug951(int amount)
126126
{
127-
DoAction(delegate {
127+
DoAction(() => {
128128
if (amount < 0)
129129
{
130130
amount = 0;
131131
}
132-
DoAction(delegate {
132+
DoAction(() => {
133133
NoOp(amount);
134134
});
135135
});
@@ -138,21 +138,21 @@ public void Bug951(int amount)
138138
public void Bug951b()
139139
{
140140
int amount = Foo();
141-
DoAction(delegate {
141+
DoAction(() => {
142142
if (amount < 0)
143143
{
144144
amount = 0;
145145
}
146-
DoAction(delegate {
146+
DoAction(() => {
147147
NoOp(amount);
148148
});
149149
});
150150
}
151151

152152
public void Bug951c(SomeData data)
153153
{
154-
DoAction(delegate {
155-
DoAction(delegate {
154+
DoAction(() => {
155+
DoAction(() => {
156156
DoSomething(data.Value);
157157
});
158158
});
@@ -165,7 +165,7 @@ public Func<int, int> Issue2143()
165165

166166
public Action<object> Bug971_DelegateWithoutParameterList()
167167
{
168-
return delegate {
168+
return (object obj) => {
169169
};
170170
}
171171

@@ -256,7 +256,7 @@ public class GenericTest<TNonCaptured, TCaptured>
256256
public Func<TCaptured> GetFunc(Func<TNonCaptured, TCaptured> f)
257257
{
258258
TCaptured captured = f(default(TNonCaptured));
259-
return delegate {
259+
return () => {
260260
Console.WriteLine(captured.GetType().FullName);
261261
return captured;
262262
};
@@ -265,7 +265,7 @@ public Func<TCaptured> GetFunc(Func<TNonCaptured, TCaptured> f)
265265
public Func<TNonCaptured, TNonCapturedMP, TCaptured> GetFunc<TNonCapturedMP>(Func<TCaptured> f)
266266
{
267267
TCaptured captured = f();
268-
return delegate (TNonCaptured a, TNonCapturedMP d) {
268+
return (TNonCaptured a, TNonCapturedMP d) => {
269269
Console.WriteLine(a.GetHashCode());
270270
Console.WriteLine(captured.GetType().FullName);
271271
return captured;
@@ -343,7 +343,7 @@ public static List<Action<int>> AnonymousMethodStoreWithinLoop()
343343
for (int i = 0; i < 10; i++)
344344
{
345345
int counter;
346-
list.Add(delegate (int x) {
346+
list.Add((int x) => {
347347
counter = x;
348348
});
349349
}
@@ -356,7 +356,7 @@ public static List<Action<int>> AnonymousMethodStoreOutsideLoop()
356356
int counter;
357357
for (int i = 0; i < 10; i++)
358358
{
359-
list.Add(delegate (int x) {
359+
list.Add((int x) => {
360360
counter = x;
361361
});
362362
}
@@ -365,7 +365,7 @@ public static List<Action<int>> AnonymousMethodStoreOutsideLoop()
365365

366366
public static Action StaticAnonymousMethodNoClosure()
367367
{
368-
return delegate {
368+
return () => {
369369
Console.WriteLine();
370370
};
371371
}
@@ -383,7 +383,7 @@ public static void NameConflict()
383383
int j;
384384
for (j = 0; j < 10; j++)
385385
{
386-
list.Add(delegate (int k) {
386+
list.Add((int k) => {
387387
for (int l = 0; l < j; l += k)
388388
{
389389
Console.WriteLine();
@@ -398,15 +398,15 @@ public static void NameConflict2(int j)
398398
List<Action<int>> list = new List<Action<int>>();
399399
for (int i = 0; i < 10; i++)
400400
{
401-
list.Add(delegate (int k) {
401+
list.Add((int k) => {
402402
Console.WriteLine(k);
403403
});
404404
}
405405
}
406406

407407
public static Action<int> NameConflict3(int i)
408408
{
409-
return delegate (int j) {
409+
return (int j) => {
410410
for (int k = 0; k < j; k++)
411411
{
412412
Console.WriteLine(k);
@@ -427,7 +427,7 @@ public static Func<int, Func<int, Func<int, int>>> CurriedAddition2(int a)
427427
public static Func<TCaptured> CapturedTypeParameter1<TNonCaptured, TCaptured>(TNonCaptured a, Func<TNonCaptured, TCaptured> f)
428428
{
429429
TCaptured captured = f(a);
430-
return delegate {
430+
return () => {
431431
Console.WriteLine(captured.GetType().FullName);
432432
return captured;
433433
};
@@ -436,7 +436,7 @@ public static Func<TCaptured> CapturedTypeParameter1<TNonCaptured, TCaptured>(TN
436436
public static Func<TCaptured> CapturedTypeParameter2<TNonCaptured, TCaptured>(TNonCaptured a, Func<TNonCaptured, List<TCaptured>> f)
437437
{
438438
List<TCaptured> captured = f(a);
439-
return delegate {
439+
return () => {
440440
Console.WriteLine(captured.GetType().FullName);
441441
return captured.FirstOrDefault();
442442
};
@@ -624,14 +624,14 @@ internal class Issue2791
624624
{
625625
public void M()
626626
{
627-
Run(delegate (object o) {
627+
Run((object o) => {
628628
try
629629
{
630630
List<int> list = o as List<int>;
631-
Action action = delegate {
631+
Action action = () => {
632632
list.Select((int x) => x * 2);
633633
};
634-
Action action2 = delegate {
634+
Action action2 = () => {
635635
list.Select((int x) => x * 2);
636636
};
637637
Console.WriteLine();

ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -818,15 +818,15 @@ public static void Call()
818818
Test<Func<int, string>>((int a) => a.ToString(), (int a) => a.ToString());
819819
Test<Func<string, char[]>>((string a) => a.ToArray(), (string a) => a.ToArray());
820820
Test<Func<bool>>(() => 'a'.CompareTo('b') < 0, () => 'a'.CompareTo('b') < 0);
821-
Test<Action<object, bool>>(delegate (object lockObj, bool lockTaken) {
821+
Test<Action<object, bool>>((object lockObj, bool lockTaken) => {
822822
Monitor.Enter(lockObj, ref lockTaken);
823823
}, (object lockObj, bool lockTaken) => Monitor.Enter(lockObj, ref lockTaken));
824824
Test<Func<string, int, bool>>((string str, int num) => int.TryParse(str, out num), (string str, int num) => int.TryParse(str, out num));
825825
Test<Func<string, SimpleType, bool>>((string str, SimpleType t) => int.TryParse(str, out t.Field), (string str, SimpleType t) => int.TryParse(str, out t.Field));
826-
Test<Action<object>>(delegate (object o) {
826+
Test<Action<object>>((object o) => {
827827
TestCall(o);
828828
}, (object o) => TestCall(o));
829-
Test<Action<object>>(delegate (object o) {
829+
Test<Action<object>>((object o) => {
830830
TestCall(ref o);
831831
}, (object o) => TestCall(ref o));
832832
}

ICSharpCode.Decompiler.Tests/TestCases/Pretty/FixProxyCalls.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ internal class H : G
9696

9797
protected internal override void Test(string test)
9898
{
99-
action = delegate (string a) {
99+
action = (string a) => {
100100
base.Test(a);
101101
};
102102
if (test.Equals(1))
@@ -119,7 +119,7 @@ public class Issue1660 : Issue1660Base
119119
{
120120
public Action<object> M(object state)
121121
{
122-
return delegate (object x) {
122+
return (object x) => {
123123
base.BaseCall(x, state, () => (object)null);
124124
};
125125
}
@@ -136,7 +136,7 @@ internal class J : I
136136
{
137137
protected internal override void Test(int a)
138138
{
139-
Action action = delegate {
139+
Action action = () => {
140140
base.Test(a);
141141
};
142142
if (a.Equals(1))

ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,11 @@ public static void NotAnObjectInitializer()
916916
public static void NotAnObjectInitializerWithEvent()
917917
{
918918
Data data = new Data();
919-
data.TestEvent += delegate {
919+
#if NET50
920+
data.TestEvent += (object? obj, EventArgs e) => {
921+
#else
922+
data.TestEvent += (object obj, EventArgs e) => {
923+
#endif
920924
Console.WriteLine();
921925
};
922926
X(Y(), data);

ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3439.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ private class Item
1212

1313
private void Test(List<string> list1)
1414
{
15-
AddAction(delegate (List<Item> list2) {
15+
AddAction((List<Item> list2) => {
1616
long num2 = 1L;
1717
foreach (string item in list1)
1818
{
@@ -28,7 +28,7 @@ private void Test(List<string> list1)
2828
{
2929
int preservedName = num;
3030
num++;
31-
AddAction(item2, delegate (object x) {
31+
AddAction(item2, (object x) => {
3232
SetValue(x, preservedName);
3333
});
3434
}

ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3751.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ private static T Infer<T>(Func<T> factory)
1313

1414
public object Trigger()
1515
{
16-
return Infer(delegate {
16+
return Infer(() => {
1717
if (Cond)
1818
{
1919
Console.WriteLine();

0 commit comments

Comments
 (0)