Skip to content

Commit 0b27eb0

Browse files
authored
Specify some lambda parameters/return type explicitly (#36454)
And make CS9236 an error
1 parent 74a3c0e commit 0b27eb0

10 files changed

+86
-73
lines changed

.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,3 +281,6 @@ dotnet_naming_rule.everything_else_naming.severity = suggestion
281281

282282
# ReSharper properties
283283
resharper_local_function_body = expression_body
284+
285+
# CS9236: Compiling requires binding the lambda expression at least 100 times
286+
dotnet_diagnostic.CS9236.severity = error

test/EFCore.Specification.Tests/Query/ComplexNavigationsQueryTestBase.cs

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2941,20 +2941,23 @@ public virtual async Task Member_pushdown_chain_3_levels_deep(bool async)
29412941
{
29422942
using var ctx = CreateContext();
29432943

2944-
var query = from l1 in ctx.LevelOne
2945-
orderby l1.Id
2946-
where (from l2 in ctx.LevelTwo
2947-
orderby l2.Id
2948-
where l2.Level1_Optional_Id == l1.Id
2949-
select (from l3 in ctx.LevelThree
2950-
orderby l3.Id
2951-
where l3.Level2_Required_Id == l2.Id
2952-
select (from l4 in ctx.LevelFour
2953-
where l4.Level3_Required_Id == l3.Id
2954-
orderby l4.Id
2955-
select l4).FirstOrDefault()).FirstOrDefault()).FirstOrDefault().Name
2956-
!= "Foo"
2957-
select l1;
2944+
#pragma warning disable CS9236 // Compiling requires binding the lambda expression at least 200 times
2945+
var query = ctx.LevelOne
2946+
.OrderBy(l1 => l1.Id)
2947+
.Where(l1 => ctx.LevelTwo
2948+
.OrderBy(l2 => l2.Id)
2949+
.Where(l2 => l2.Level1_Optional_Id == l1.Id)
2950+
.Select(l2 => ctx.LevelThree
2951+
.OrderBy(l3 => l3.Id)
2952+
.Where(l3 => l3.Level2_Required_Id == l2.Id)
2953+
.Select(l3 => ctx.LevelFour
2954+
.Where(bool (Level4 l4) => l4.Level3_Required_Id == l3.Id)
2955+
.OrderBy(int (Level4 l4) => l4.Id)
2956+
.FirstOrDefault())
2957+
.FirstOrDefault())
2958+
.FirstOrDefault()
2959+
.Name != "Foo");
2960+
#pragma warning restore CS9236
29582961

29592962
_ = async ? await query.ToListAsync() : query.ToList();
29602963
}
@@ -2965,18 +2968,20 @@ public virtual async Task Member_pushdown_chain_3_levels_deep_entity(bool async)
29652968
{
29662969
using var ctx = CreateContext();
29672970

2968-
var query = from l1 in ctx.LevelOne
2969-
orderby l1.Id
2970-
select (from l2 in ctx.LevelTwo
2971-
orderby l2.Id
2972-
where l2.Level1_Optional_Id == l1.Id
2973-
select (from l3 in ctx.LevelThree
2974-
orderby l3.Id
2975-
where l3.Level2_Required_Id == l2.Id
2976-
select (from l4 in ctx.LevelFour
2977-
where l4.Level3_Required_Id == l3.Id
2978-
orderby l4.Id
2979-
select l4).FirstOrDefault()).FirstOrDefault()).FirstOrDefault();
2971+
var query = ctx.LevelOne
2972+
.OrderBy(l1 => l1.Id)
2973+
.Select(l1 => ctx.LevelTwo
2974+
.OrderBy(l2 => l2.Id)
2975+
.Where(l2 => l2.Level1_Optional_Id == l1.Id)
2976+
.Select(l2 => ctx.LevelThree
2977+
.OrderBy(l3 => l3.Id)
2978+
.Where(l3 => l3.Level2_Required_Id == l2.Id)
2979+
.Select(l3 => ctx.LevelFour
2980+
.Where(bool (Level4 l4) => l4.Level3_Required_Id == l3.Id)
2981+
.OrderBy(int (Level4 l4) => l4.Id)
2982+
.FirstOrDefault())
2983+
.FirstOrDefault())
2984+
.FirstOrDefault());
29802985

29812986
_ = async ? await query.ToListAsync() : query.ToList();
29822987
}
@@ -4052,7 +4057,7 @@ public virtual Task Max_in_multi_level_nested_subquery(bool async)
40524057
LevelFour = new
40534058
{
40544059
xx.OneToOne_Required_FK2.OneToOne_Required_FK3.Id,
4055-
Result = (xx.OneToOne_Required_FK2.OneToMany_Optional3.Max(xxx => (int?)xxx.Id) ?? 0)
4060+
Result = (xx.OneToOne_Required_FK2.OneToMany_Optional3.Max(int? (Level4 xxx) => (int?)xxx.Id) ?? 0)
40564061
> 1
40574062
}
40584063
}

test/EFCore.Specification.Tests/Query/Ef6GroupByTestBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ public virtual Task Min_Elements_from_LINQ_101(bool async)
360360
ss => from p in ss.Set<ProductForLinq>()
361361
group p by p.Category
362362
into g
363-
let minPrice = g.Min(p => p.UnitPrice)
363+
let minPrice = g.Min(decimal (ProductForLinq p) => p.UnitPrice)
364364
select new { Category = g.Key, CheapestProducts = g.Where(p => p.UnitPrice == minPrice) }));
365365

366366
[ConditionalTheory]
@@ -383,7 +383,7 @@ public virtual Task Max_Elements_from_LINQ_101(bool async)
383383
ss => from p in ss.Set<ProductForLinq>()
384384
group p by p.Category
385385
into g
386-
let minPrice = g.Max(p => p.UnitPrice)
386+
let minPrice = g.Max(decimal (ProductForLinq p) => p.UnitPrice)
387387
select new { Category = g.Key, MostExpensiveProducts = g.Where(p => p.UnitPrice == minPrice) }));
388388

389389
[ConditionalTheory]

test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -139,23 +139,23 @@ public virtual Task Sum_over_subquery(bool async)
139139
=> AssertSum(
140140
async,
141141
ss => ss.Set<Customer>(),
142-
selector: c => c.Orders.Sum(o => o.OrderID));
142+
selector: c => c.Orders.Sum(int (Order o) => o.OrderID));
143143

144144
[ConditionalTheory]
145145
[MemberData(nameof(IsAsyncData))]
146146
public virtual Task Sum_over_nested_subquery(bool async)
147147
=> AssertSum(
148148
async,
149149
ss => ss.Set<Customer>(),
150-
selector: c => c.Orders.Sum(o => 5 + o.OrderDetails.Sum(od => od.ProductID)));
150+
selector: c => c.Orders.Sum(int (Order o) => 5 + o.OrderDetails.Sum(int (OrderDetail od) => od.ProductID)));
151151

152152
[ConditionalTheory]
153153
[MemberData(nameof(IsAsyncData))]
154154
public virtual Task Sum_over_min_subquery(bool async)
155155
=> AssertSum(
156156
async,
157157
ss => ss.Set<Customer>(),
158-
selector: c => c.Orders.Sum(o => 5 + o.OrderDetails.Min(od => od.ProductID)));
158+
selector: c => c.Orders.Sum(int (Order o) => 5 + o.OrderDetails.Min(int (OrderDetail od) => od.ProductID)));
159159

160160
[ConditionalTheory]
161161
[MemberData(nameof(IsAsyncData))]
@@ -270,23 +270,23 @@ public virtual Task Average_over_subquery(bool async)
270270
=> AssertAverage(
271271
async,
272272
ss => ss.Set<Customer>(),
273-
selector: c => c.Orders.Sum(o => o.OrderID));
273+
selector: c => c.Orders.Sum(int (Order o) => o.OrderID));
274274

275275
[ConditionalTheory]
276276
[MemberData(nameof(IsAsyncData))]
277277
public virtual Task Average_over_nested_subquery(bool async)
278278
=> AssertAverage(
279279
async,
280280
ss => ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(3),
281-
selector: c => (decimal)c.Orders.Average(o => 5 + o.OrderDetails.Average(od => od.ProductID)));
281+
selector: c => (decimal)c.Orders.Average(double (Order o) => 5 + o.OrderDetails.Average(int (OrderDetail od) => od.ProductID)));
282282

283283
[ConditionalTheory]
284284
[MemberData(nameof(IsAsyncData))]
285285
public virtual Task Average_over_max_subquery(bool async)
286286
=> AssertAverage(
287287
async,
288288
ss => ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(3),
289-
selector: c => (decimal)c.Orders.Average(o => 5 + o.OrderDetails.Max(od => od.ProductID)));
289+
selector: c => (decimal)c.Orders.Average(int (Order o) => 5 + o.OrderDetails.Max(int (OrderDetail od) => od.ProductID)));
290290

291291
[ConditionalTheory]
292292
[MemberData(nameof(IsAsyncData))]
@@ -447,15 +447,15 @@ public virtual Task Min_over_nested_subquery(bool async)
447447
=> AssertMin(
448448
async,
449449
ss => ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(3),
450-
selector: c => c.Orders.Min(o => 5 + Enumerable.Min(o.OrderDetails, od => od.ProductID)));
450+
selector: c => c.Orders.Min(o => 5 + Enumerable.Min(o.OrderDetails, int (OrderDetail od) => od.ProductID)));
451451

452452
[ConditionalTheory]
453453
[MemberData(nameof(IsAsyncData))]
454454
public virtual Task Min_over_max_subquery(bool async)
455455
=> AssertMin(
456456
async,
457457
ss => ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(3),
458-
selector: c => c.Orders.Min(o => 5 + o.OrderDetails.Max(od => od.ProductID)));
458+
selector: c => c.Orders.Min(o => 5 + o.OrderDetails.Max(int (OrderDetail od) => od.ProductID)));
459459

460460
[ConditionalTheory]
461461
[MemberData(nameof(IsAsyncData))]
@@ -494,15 +494,15 @@ public virtual Task Max_over_nested_subquery(bool async)
494494
=> AssertMax(
495495
async,
496496
ss => ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(3),
497-
selector: c => c.Orders.Max(o => 5 + Enumerable.Max(o.OrderDetails, od => od.ProductID)));
497+
selector: c => c.Orders.Max(o => 5 + Enumerable.Max(o.OrderDetails, int (OrderDetail od) => od.ProductID)));
498498

499499
[ConditionalTheory]
500500
[MemberData(nameof(IsAsyncData))]
501501
public virtual Task Max_over_sum_subquery(bool async)
502502
=> AssertMax(
503503
async,
504504
ss => ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(3),
505-
selector: c => c.Orders.Max(o => 5 + o.OrderDetails.Sum(od => od.ProductID)));
505+
selector: c => c.Orders.Max(o => 5 + o.OrderDetails.Sum(int (od) => od.ProductID)));
506506

507507
[ConditionalTheory]
508508
[MemberData(nameof(IsAsyncData))]

test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public virtual Task GroupBy_Property_Select_Average_with_group_enumerable_projec
3737
async,
3838
ss => ss.Set<Order>().Where(o => o.Customer.City != "London")
3939
.GroupBy(o => o.CustomerID, (k, es) => new { k, es })
40-
.Select(g => g.es.Average(o => o.OrderID))));
40+
.Select(g => g.es.Average(int (Order o) => o.OrderID))));
4141

4242
[ConditionalTheory]
4343
[MemberData(nameof(IsAsyncData))]
@@ -1580,7 +1580,7 @@ into g
15801580
{
15811581
s.Month,
15821582
s.Total,
1583-
Payment = ss.Set<Order>().Where(e => e.OrderDate.Value.Month == s.Month).Sum(e => e.OrderID)
1583+
Payment = ss.Set<Order>().Where(e => e.OrderDate.Value.Month == s.Month).Sum(int (Order e) => e.OrderID)
15841584
},
15851585
elementSorter: e => (e.Month, e.Total),
15861586
elementAsserter: (e, a) =>
@@ -1775,7 +1775,7 @@ public virtual Task GroupBy_Aggregate_Join_converted_from_SelectMany(bool async)
17751775
ss => from c in ss.Set<Customer>()
17761776
from o in ss.Set<Order>().GroupBy(o => o.CustomerID)
17771777
.Where(g => g.Count() > 5)
1778-
.Select(g => new { CustomerID = g.Key, LastOrderID = g.Max(o => o.OrderID) })
1778+
.Select(g => new { CustomerID = g.Key, LastOrderID = g.Max(int (Order o) => o.OrderID) })
17791779
.Where(c1 => c.CustomerID == c1.CustomerID)
17801780
select c);
17811781

@@ -1787,7 +1787,7 @@ public virtual Task GroupBy_Aggregate_LeftJoin_converted_from_SelectMany(bool as
17871787
ss => from c in ss.Set<Customer>()
17881788
from o in ss.Set<Order>().GroupBy(o => o.CustomerID)
17891789
.Where(g => g.Count() > 5)
1790-
.Select(g => new { CustomerID = g.Key, LastOrderID = g.Max(o => o.OrderID) })
1790+
.Select(g => new { CustomerID = g.Key, LastOrderID = g.Max(int (Order o) => o.OrderID) })
17911791
.Where(c1 => c.CustomerID == c1.CustomerID)
17921792
.DefaultIfEmpty()
17931793
select c);
@@ -2342,7 +2342,7 @@ from oc1 in ss.Set<Order>()
23422342
.Where(x => x.CustomerID == c.CustomerID).DefaultIfEmpty()
23432343
group new { c.CustomerID, oc1.Count } by c.CustomerID
23442344
into g
2345-
select new { CustomerID = g.Key, Count = g.Sum(x => x.Count) }).Where(x => x.CustomerID == c1.CustomerID)
2345+
select new { CustomerID = g.Key, Count = g.Sum(int? (x) => x.Count) }).Where(x => x.CustomerID == c1.CustomerID)
23462346
.DefaultIfEmpty()
23472347
select new
23482348
{
@@ -2357,7 +2357,7 @@ from oc1 in ss.Set<Order>()
23572357
.Where(x => x.CustomerID == c.CustomerID).DefaultIfEmpty()
23582358
group new { c.CustomerID, Count = oc1.MaybeScalar(e => e.Count) } by c.CustomerID
23592359
into g
2360-
select new { CustomerID = g.Key, Count = g.Sum(x => x.Count) }).Where(x => x.CustomerID == c1.CustomerID)
2360+
select new { CustomerID = g.Key, Count = g.Sum(int? (x) => x.Count) }).Where(x => x.CustomerID == c1.CustomerID)
23612361
.DefaultIfEmpty()
23622362
select new
23632363
{
@@ -3200,7 +3200,7 @@ public virtual Task Complex_query_with_groupBy_in_subquery1(bool async)
32003200
Subquery = c.Orders
32013201
.Select(o => new { First = o.CustomerID, Second = o.OrderID })
32023202
.GroupBy(x => x.First)
3203-
.Select(g => new { Sum = g.Sum(x => x.Second) }).ToList()
3203+
.Select(g => new { Sum = g.Sum(int (x) => x.Second) }).ToList()
32043204
}),
32053205
elementSorter: e => e.Key,
32063206
elementAsserter: (e, a) =>
@@ -3222,7 +3222,7 @@ public virtual Task Complex_query_with_groupBy_in_subquery2(bool async)
32223222
Subquery = c.Orders
32233223
.Select(o => new { First = o.CustomerID, Second = o.OrderID })
32243224
.GroupBy(x => x.First)
3225-
.Select(g => new { Max = g.Max(x => x.First.Length), Sum = g.Sum(x => x.Second) }).ToList()
3225+
.Select(g => new { Max = g.Max(int (x) => x.First.Length), Sum = g.Sum(int (x) => x.Second) }).ToList()
32263226
}),
32273227
elementSorter: e => e.Key,
32283228
elementAsserter: (e, a) =>
@@ -3244,7 +3244,7 @@ public virtual Task Complex_query_with_groupBy_in_subquery3(bool async)
32443244
Subquery = ss.Set<Order>()
32453245
.Select(o => new { First = o.CustomerID, Second = o.OrderID })
32463246
.GroupBy(x => x.First)
3247-
.Select(g => new { Max = g.Max(x => x.First.Length), Sum = g.Sum(x => x.Second) }).ToList()
3247+
.Select(g => new { Max = g.Max(int (x) => x.First.Length), Sum = g.Sum(int (x) => x.Second) }).ToList()
32483248
}),
32493249
elementSorter: e => e.Key,
32503250
elementAsserter: (e, a) =>
@@ -3266,7 +3266,7 @@ public virtual Task Complex_query_with_groupBy_in_subquery4(bool async)
32663266
Subquery = c.Orders
32673267
.Select(o => new { First = o.OrderID, Second = o.Customer.City + o.CustomerID })
32683268
.GroupBy(x => x.Second)
3269-
.Select(g => new { Sum = g.Sum(x => x.First), Count = g.Count(x => x.Second.StartsWith("Lon")) }).ToList()
3269+
.Select(g => new { Sum = g.Sum(int (x) => x.First), Count = g.Count(x => x.Second.StartsWith("Lon")) }).ToList()
32703270
}),
32713271
elementSorter: e => e.Key,
32723272
elementAsserter: (e, a) =>
@@ -3288,7 +3288,7 @@ into grouping
32883288
{
32893289
Sum = grouping.Sum(x => x.ProductID + x.OrderID * 1000),
32903290
Subquery = (from c in ss.Set<Customer>()
3291-
where c.CustomerID.Length < grouping.Min(x => x.OrderID / 100)
3291+
where c.CustomerID.Length < grouping.Min(int (OrderDetail x) => x.OrderID / 100)
32923292
orderby c.CustomerID
32933293
select new { c.CustomerID, c.City }).ToList()
32943294
},
@@ -3381,7 +3381,7 @@ public virtual Task GroupBy_aggregate_from_multiple_query_in_same_projection_2(b
33813381
{
33823382
g.Key,
33833383
A = ss.Set<Employee>().Where(e => e.City == "Seattle").GroupBy(e => e.City)
3384-
.Select(g2 => g2.Count() + g.Min(e => e.OrderID))
3384+
.Select(g2 => g2.Count() + g.Min(int (Order e) => e.OrderID))
33853385
.OrderBy(e => 1)
33863386
.FirstOrDefault()
33873387
}),

test/EFCore.Specification.Tests/Query/NorthwindJoinQueryTestBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,7 @@ public virtual Task GroupJoin_aggregate_nested_anonymous_key_selectors(bool asyn
721721
ss.Set<Order>(),
722722
x => new { x.CustomerID, Nested = new { x.City, Year = 1996 } },
723723
x => new { x.CustomerID, Nested = new { City = "London", x.OrderDate.Value.Year } },
724-
(c, g) => new { c.CustomerID, Sum = g.Sum(x => x.CustomerID.Length) }),
724+
(c, g) => new { c.CustomerID, Sum = g.Sum(int (x) => x.CustomerID.Length) }),
725725
elementSorter: e => e.CustomerID));
726726

727727
[ConditionalTheory]

test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,6 +1833,7 @@ public virtual Task Where_query_composition3(bool async)
18331833
where c1.City == ss.Set<Customer>().OrderBy(c => c.CustomerID).First(c => c.IsLondon).City
18341834
select c1));
18351835

1836+
#pragma warning disable CS9236 // Compiling requires binding the lambda expression at least 200 times
18361837
[ConditionalTheory]
18371838
[MemberData(nameof(IsAsyncData))]
18381839
public virtual Task Where_query_composition4(bool async)
@@ -1842,9 +1843,10 @@ public virtual Task Where_query_composition4(bool async)
18421843
ss => from c1 in ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(2)
18431844
where c1.City
18441845
== (from c2 in ss.Set<Customer>().OrderBy(c => c.CustomerID)
1845-
from c3 in ss.Set<Customer>().OrderBy(c => c.IsLondon).ThenBy(c => c.CustomerID)
1846+
from c3 in ss.Set<Customer>().OrderBy(bool (Customer c) => c.IsLondon).ThenBy(string (Customer c) => c.CustomerID)
18461847
select new { c3 }).First().c3.City
18471848
select c1));
1849+
#pragma warning restore CS9236
18481850

18491851
[ConditionalTheory]
18501852
[MemberData(nameof(IsAsyncData))]
@@ -3990,6 +3992,7 @@ public virtual Task Complex_query_with_repeated_query_model_compiles_correctly(b
39903992
where customers.Any()
39913993
select customers).Any()));
39923994

3995+
#pragma warning disable CS9236 // Compiling requires binding the lambda expression at least 200 times
39933996
[ConditionalTheory]
39943997
[MemberData(nameof(IsAsyncData))]
39953998
public virtual Task Complex_query_with_repeated_nested_query_model_compiles_correctly(bool async)
@@ -4001,10 +4004,11 @@ public virtual Task Complex_query_with_repeated_nested_query_model_compiles_corr
40014004
outer =>
40024005
(from c in ss.Set<Customer>()
40034006
let customers = ss.Set<Customer>().Where(
4004-
cc => ss.Set<Customer>().OrderBy(inner => inner.CustomerID).Take(10).Distinct().Any())
4007+
cc => ss.Set<Customer>().OrderBy(string (Customer inner) => inner.CustomerID).Take(10).Distinct().Any())
40054008
.Select(cc => cc.CustomerID).ToList()
40064009
where customers.Any()
40074010
select customers).Any()));
4011+
#pragma warning restore CS9236
40084012

40094013
[ConditionalTheory]
40104014
[MemberData(nameof(IsAsyncData))]

0 commit comments

Comments
 (0)