如何使用 LINQ 从泛型列表中获取下一个适当的值
本文关键字:下一个 获取 LINQ 何使用 泛型 列表 | 更新日期: 2023-09-27 18:35:05
我有一个类:
public class CounselPoints
{
public int CounselNum { get; set; }
public String CounselPoint { get; set; }
public bool BR { get; set; }
public bool ICRVBS { get; set; }
}
。以及该类的通用列表:
List<CounselPoints> counselPoints = AYttFMConstsAndUtils.DeserializeCounselPointsFile();
我想从该通用列表中检索下一个合适的 CounselPoint,其中包含可以用 SQL 表示的逻辑,如下所示:
SELECT TOP 1 CounselNumber
FROM COUNSELPOINTSLU
WHERE BR IS TRUE
AND CounselNumber > @LastCounselPoint;
我调用此方法来尝试获取该值,并且像这样对它大发雷霆:
public static int GetNextBibleReadingCounselPoint(int LastCounselPoint)
{
List<CounselPoints> counselPoints = AYttFMConstsAndUtils.DeserializeCounselPointsFile();
return counselPoints.FirstOrDefault(i => i.CounselNum).Where(j => j.BR).Where(k => k.CounselNum > LastCounselPoint);
}
在"英语"中,我试图说,"给我第一个CounselNum,它比传入的arg(LastCounselPoint)更大,并且BR是正确的"
例如,如果我传入 17,并且 CounselNum val 为 18 的 counselPoint "记录"也将 BR 设置为 true,它应该返回 18。很简单,不是吗?
但是我看似丑陋的,或者充其量是尴尬的尝试,甚至没有编译;我得到:
错误 CS0029 无法将类型"int"隐式转换为"bool"
。和:
错误 CS1662 无法将 lambda 表达式转换为预期的委托类型,因为块中的某些返回类型不能隐式转换为委托返回类型
我不知道为什么它认为我试图转换为布尔值,我绝对不会发现第二个错误。
如果我将代码更改为以下内容:
return counselPoints.FirstOrDefault(i => i.CounselNum > LastCounselPoint).Where(j => j.BR).Select(k => k.CounselNum );
我得到:
错误 CS1061 "CounselPoints"不包含"Where"的定义,并且找不到接受类型为"CounselPoints"的第一个参数的扩展方法"Where"(您是否缺少 using 指令或程序集引用?
。这也只导致我告诉编译器,"除了九个,所有人都下来了,pard;把他们放在另一条巷子里。
解开这个难题的关键是什么?
使用查询时,首先需要使用过滤条件,然后才调用FirstOrDefault
:
return counselPoints
.Where(j => j.BR)
.Where(k => k.CounselNum > LastCounselPoint)
.Select(i => i.CounselNum)
.FirstOrDefault();
有两种类型的 LINQ 查询运算符 - 即时查询运算符和延迟查询运算符。 Where
是延迟运算符的示例,FirstOrDefault
是直接操作者。
在代码中,您在无序列表上使用FirstOrDefault
,因此立即筛选了初始列表。
在我提供的示例代码中,我首先使用延迟运算符来定义筛选器,然后才使用即时函数来检索结果。
我在你的例子(以及其他 anwsers 中)看到你写了这样的第一个默认值: .FirstOrDefault(i => i.CounselNum)
但我认为你不需要这个。
将第一个默认值视为筛选器而不是选择。
所以相反,你需要这样写
return counselPoints
.Where(cp => cp.BR && cp.CounselNum > LastCounselPoint) // where clause
.Select(cp => cp.CounselNum) // select part
.FirstOrDefault(); // get top 1 only
*更新>存在
正如@Jannik指出的那样,当没有匹配项时,上述返回零而不是 null。
如果同时测试存在很重要,那么你可以这样写。
CounselPoint cp = counselPoints
.Where(cp => cp.BR && cp.CounselNum > LastCounselPoint) // where clause
.FirstOrDefault(); // get top 1 object of type CounselPoint
if (cp == null)
return null;
return cp.CounselNum;
请注意,方法的返回类型必须是可为 null 的 int。请参阅下面添加的?
。
public static int? GetNextBibleReadingCounselPoint(int LastCounselPoint)
。然后我猜你的调用代码来检查结果
int? result = GetNextBibleReadingCounselPoint(lastCounselPoint);
if (result.HasValue) {
// something was returned
} else {
// nothing was returned
int num = result.Value;
}
*更新2>订单
考虑您的原始 SQL - 我想知道您是否不考虑顺序?
也许您应该通过在底部添加订单:
SELECT TOP 1 CounselNumber
FROM COUNSELPOINTSLU
WHERE BR IS TRUE
AND CounselNumber > @LastCounselPoint
ORDER BY CounselNumber; // ascending
在这种情况下,您可以在 linq 语句中的 where 子句之前添加 order-by;像这样
return counselPoints
.OrderBy(cp => cp.CounselNum) // order by ascending
.Where( ... rest of code
我认为dotnetom和Chris Moutray已经回答了这个问题,我只想给一个小的旁注:
下次遇到 LINQ 语句问题时,请尝试将它们拆分为单独的语句。这样做你会看到FirstOrDefault()
在 Where() 之前没有任何意义,因为它会返回一个对象,你不能在单个对象上使用 where,对吧?:)
试试这个....
counselPoints
.Where(j => j.BR && j.CounselNum > LastCounselPoint)
.FirstOrDefault();