C# 在lambda中使用扩展方法时,C 5.0 ForEach无效args错误

C# 在lambda中使用扩展方法时,C 5.0 ForEach无效args错误,c#,C#,每种方法我都遇到过奇怪的行为。当我写下这段代码时: var result = repository.Data.Where(<some_long_selector>).ToList(); result.ForEach(e => { e.x = CalcX(e); e.y = GetAllYs().FirstOrDefault(y => y.Id == e.x) }); 我得到ForEach方法的无效参数错误,即某些类型错误。这对我来说是很意外的。我理解可能

每种方法我都遇到过奇怪的行为。当我写下这段代码时:

var result = repository.Data.Where(<some_long_selector>).ToList();
result.ForEach(e =>
{
    e.x = CalcX(e);
    e.y = GetAllYs().FirstOrDefault(y => y.Id == e.x)
});
我得到ForEach方法的无效参数错误,即某些类型错误。这对我来说是很意外的。我理解可能的解决方法,但我只想知道这是如何发生的,为什么会发生,以及在保持这个或稍微修改的Elvis扩展功能的同时,最省力的纠正方法是什么


另外,我是Java开发人员,在我们的团队开发替换代码时需要支持一些遗留C代码。所以,很抱歉,如果我错过了一些明显的东西,那么通过传递字符串empty和Elvis方法的实现,我们不清楚您使用的是什么类型的对象。 我的建议是尝试以不同的方式编写ForEach循环,并将代码分开,以便在调试时一步一步地接收结果,如

ForEach (var item in result)
{
 item.x = CalcX(item);
 var yResult = GetAllYs().FirstOrDefault(z => z.Id == item.Id);
 //then your faulty code to find out your problem while debugging the Elvis method
 item.y = yResult.Elvis(new Y("empty"))
}

Elvis的定义无效。它必须是这样的:

    public static T Elvis<T>(this T? instance, T defaultValue) where T : struct

同样,在您的示例中,您调用Evis而不是Elvis。

Elvis还必须将其泛型参数约束为struct或class,如下所示:

公共静态T这是T吗?实例,T defaultValue T:在哪里上课 { ... } 或

公共静态T这是T吗?实例,T defaultValue 其中T:struct { ... } 这是因为直到最近,该语言还没有通用可空性的概念——只有结构可以显式地设置为可空,因为无论您喜欢与否,类都是可空的。可空结构被编译器悄悄地包装在可空类型中,一切正常

这意味着在泛型签名中使用nullable运算符需要参数是一个结构,因为直到最近才对类有意义。因此,需要显式结构约束才能使用运算符

然而,现在我们也有了可为null的引用类型,您可能会认为,允许可为null的操作符通常不受约束是有意义的-但是由于旧的方式,这会导致某些地方出现混乱,因此语言团队说“不”,请看这里:

结果是,您必须有一个显式约束才能以这种方式使用nullable运算符-并且您必须在引用类型或结构类型上工作的扩展方法之间进行选择,但我认为不能两者都选择


另一个有用的链接:

发布实际错误文本e定义在哪里,为什么在循环中不断重新分配它的x和y属性?@PanagiotisKanavos,它是俄语。这会有帮助吗?也许你已经知道了,但不像??运算符,您的Elvis方法将始终执行新的Y…@RufusL e未全部定义。它是从三个不同的来源收集的,用于指出我的拼写错误。至于你的答案:它不起作用,因为Y是可空的type@ksbes可为空的T?只能在结构上使用,而不能在类引用类型上使用,因为这些引用类型至少直到最近才始终可以为空。所以也许就把它去掉吧?是的,你们都是对的!!!但仍然奇怪的是,ForEach方法报告了错误。我的更改是公共静态T elvist这个T实例,TdefaultValue@ksbes我觉得杰森的答案更完整,你应该接受他的答案,而不是我的绿色复选标记。这没有帮助:还是一样的例外。似乎仅仅在lambda内部使用扩展就改变了lambda类型。当我刚刚把行var t=extensions.Elvis放进去时,出现了一个错误!
ForEach (var item in result)
{
 item.x = CalcX(item);
 var yResult = GetAllYs().FirstOrDefault(z => z.Id == item.Id);
 //then your faulty code to find out your problem while debugging the Elvis method
 item.y = yResult.Elvis(new Y("empty"))
}
    public static T Elvis<T>(this T? instance, T defaultValue) where T : struct