LINQ最大()与空值
我有一个列表,其中包含一堆点(与X和Y组件)。
我想获得列表中所有点的最大X,如下所示:
double max = pointList.Max(p=> pX); 问题是当我在列表中有一个空而不是一个点。 解决这个问题最好的办法是什么?
那么,你可以把它们过滤出来:
 pointList.Where(p => p != null).Max(p => pX) 
 另一方面,如果要将null视为具有X坐标0 (或类似)的点,则可以这样做: 
 pointList.Max(p => p == null ? 0 : pX) 
请注意,如果序列是空的,这两种技术都会抛出。 一个解决方法(如果可取的话)将是:
 pointList.DefaultIfEmpty().Max(p => p == null ? 0 : pX) 
如果您想为空点的X提供默认值:
 pointList.Max(p => p == null ? 0 : pX) 
或者为空列表提供默认值:
 int max = points.Where(p => p != null) .Select(p => pX) .DefaultIfEmpty() .Max(); 
 在这种情况下,我不推荐使用DefaultIfEmpty ,因为与其他select相比,它会产生一个相当大的SQL。 
请看这个例子:
 我们有一个页面的模块列表,并希望获得“sorting”列的最大值。 如果列表没有logging,则返回null。  DefaultIfEmpty检查null,并在DefaultIfEmpty空时返回列数据types的默认值。 
 var max = db.PageModules.Where(t => t.PageId == id).Select(t => t.Sort).DefaultIfEmpty().Max(); 
这会产生以下SQL:
 exec sp_executesql N'SELECT [GroupBy1].[A1] AS [C1] FROM ( SELECT MAX([Join1].[A1]) AS [A1] FROM ( SELECT CASE WHEN ([Project1].[C1] IS NULL) THEN 0 ELSE [Project1].[Sort] END AS [A1] FROM ( SELECT 1 AS X ) AS [SingleRowTable1] LEFT OUTER JOIN (SELECT [Extent1].[Sort] AS [Sort], cast(1 as tinyint) AS [C1] FROM [dbo].[PageModules] AS [Extent1] WHERE [Extent1].[PageId] = @p__linq__0 ) AS [Project1] ON 1 = 1 ) AS [Join1] ) AS [GroupBy1]',N'@p__linq__0 int',@p__linq__0=11 go 
 如果我们将该列转换为可空,并让Convert.ToInt32()处理null,如下所示: 
 var max = Convert.ToInt32(db.PageModules.Where(t => t.PageId == id).Max(t => (int?)t.Sort)); 
然后我们得到下面的SQL:
 exec sp_executesql N'SELECT [GroupBy1].[A1] AS [C1] FROM ( SELECT MAX([Extent1].[Sort]) AS [A1] FROM [dbo].[PageModules] AS [Extent1] WHERE [Extent1].[PageId] = @p__linq__0 ) AS [GroupBy1]',N'@p__linq__0 int',@p__linq__0=11 go 
我真的可以推荐使用ExpressProfiler来检查执行的SQL: http : //expressprofiler.codeplex.com/
最后的Linqexpression式也可以写成:
 var max = Convert.ToInt32(db.PageModules.Where(t => t.PageId == id).Select(t => (int?)t.Sort).Max()); 
 并会产生相同的SQL,但我更喜欢简洁的.Max(t => (int?)t.Sort) 。 
 double max = pointList.Where(p=>p != null).Max(p=>pX) 
应该pipe用。
尝试投射可空
 double max = (double?)pointList.Max(p => pX); 
更多: 最大或默认?
为什么不简单:
 double? maxOrNull = pointList. .Where(p => p != null) .OrderByDescending(p => px) .FirstOrDefault(); double max = 0; if (maxOrNull.HasValue) max = maxOrNull.Value; 
这将在内存列表和Linq2Sql中工作,也可能有效。
在expression式中放置一个可为空的转换,以确保空白列表将转换为空值。 您可以添加默认值。
 double max = pointList.Max(p=>(double?)pX) ?? 0;