在可为空的十进制属性上使用 Math.Abs
Posted
技术标签:
【中文标题】在可为空的十进制属性上使用 Math.Abs【英文标题】:Using Math.Abs on nullable decimal property 【发布时间】:2022-01-17 18:27:28 【问题描述】:我有一个类型的对象。
class A
public int Idget;set;
public decimal? Num get;set;
然后我从 db 填充了 List<A> objList
数据。
我需要将 Num 设为正数,所以
我尝试执行以下操作。
objList = objList.ForEach(x=>x.Num = Math.Abs(x.Num));
由于 Num 是可以为空的 decimal ,我无法在 Linq 中使用它。如何使用它,以便我可以跳过空值并使用 Math.abs 将 -ve 值转换为 +ve 1?
【问题讨论】:
如何使用它以便我可以跳过空值 - 这不是很清楚,但如果你想删除Num
为空的值,你可以这样做 - objList = objList.Where(o => o.Num.HasValue).Select(o => new A Id = o.Id, Num = Math.Abs(o.Num.Value) ).ToList();
@stuartd 我很确定“跳过”意味着忽略而不是从列表中删除。
@JohnathanBarclay:是的,你是对的。跳过意味着忽略它
@JohnathanBarclay 我认为这是有道理的,但值被分配回objList
【参考方案1】:
我不会使用List<T>.ForEach()
来改变列表。相反,我会使用一个简单的foreach
循环,如下所示:
foreach (var item in objList.Where(item => item.Num != null))
item.Num = Math.Abs(item.Num!.Value);
注意:如果使用可空检查,您必须使用!
来抑制item.Num!.Value
中的警告,因为编译器不够聪明,无法确定因为Where
它不能为空。
另请注意,这种方法避免了将 null
冗余分配给已经为空的 Num
,这在其他解决方案中会发生。
(请参阅Eric Lippert's post on foreach vs ForEach,了解为什么不应该使用List<T>.ForEach()
来改变列表。)
【讨论】:
Eric Lippert 讨论了为什么没有将ForEach
添加到 LINQ。唯一提到List<T>.ForEach
是您“在迭代列表时不应该对其进行变异”,但这正是您对标准foreach
所做的事情。
@JohnathanBarclay 注意 Eric 说的部分 Doing this lets you rewrite this perfectly clear code:
... into this code:
。我同意他的观点,即使用List<T>.ForEach()
的代码不是很清楚。 那是我想提请注意的。【参考方案2】:
ForEach
不是 LINQ 的一部分,而是List<T>
上的method defined,它返回void
(因此您不能将其结果分配给objList
,即objList = objList.ForEach
)。
您可以使用ternary operator 来检查x.Num
是否具有价值并将该值用于Math.Abs
:
objList.ForEach(x => x.Num = x.Num.HasValue ? Math.Abs(x.Num.Value) : null);
【讨论】:
【参考方案3】:ForEach
不是 LINQ,it's an instance method on List<T>
会更新列表。
当Num
不为空时,您可以使用三元表达式仅应用Math.Abs
:
objList.ForEach(x => x.Num = x.Num is decimal d ? Math.Abs(d) : null);
【讨论】:
这不会更新任何东西吗?并且 x.Num 仍然是decimal?
类型,无论您的空卡盘如何,所以我很确定您仍然需要使用 x.Num.Value以上是关于在可为空的十进制属性上使用 Math.Abs的主要内容,如果未能解决你的问题,请参考以下文章
C# winforms:将可空类型绑定到其他属性(不是文本)时出错