List.RemoveAll结合Lambda表达式异常:误删全部元素求助
问题分析与解决方案
嘿,这个坑我踩过!你遇到的问题根源在于浮点数的精度比较问题,而不是RemoveAll方法本身的逻辑错误。
为什么会误删所有元素?
你的代码里直接用==比较Latitude和Longitude:
y.Position.Latitude == x.Position.Latitude && y.Position.Longitude == x.Position.Longitude
但Latitude和Longitude几乎都是double(或其他浮点类型),这类数值在计算机中是近似存储的——哪怕两个坐标看起来完全一样,底层二进制可能存在极其微小的精度差异(比如1.23456789和1.2345678900000001)。这种差异会导致==的判断结果完全不符合预期,最终让RemoveAll的筛选条件错误地匹配了所有元素,所以才会把整个列表清空。
正确的解决方法
不要直接用==比较浮点类型的坐标,而是判断两个值的差值的绝对值小于一个极小的阈值(比如1e-9,这个值可以根据你的坐标精度需求调整)。
修改后的代码如下:
// 定义一个精度阈值,适配坐标的精度需求 const double precisionThreshold = 1e-9; listCurrentPostsMarkers.RemoveAll(x => listRemoveMarkers.Exists(y => Math.Abs(y.Position.Latitude - x.Position.Latitude) < precisionThreshold && Math.Abs(y.Position.Longitude - x.Position.Longitude) < precisionThreshold ) );
更优雅的优化方案
如果你的项目里经常需要比较坐标,可以封装一个比较器或者重写坐标类的Equals方法,避免重复写精度判断逻辑:
- 自定义
IEqualityComparer:
public class PositionEqualityComparer : IEqualityComparer<Position> { private readonly double _threshold; public PositionEqualityComparer(double threshold = 1e-9) { _threshold = threshold; } public bool Equals(Position x, Position y) { if (x == null || y == null) return x == y; return Math.Abs(x.Latitude - y.Latitude) < _threshold && Math.Abs(x.Longitude - y.Longitude) < _threshold; } public int GetHashCode(Position obj) { // 根据精度取整后计算哈希,避免精度差异导致哈希值不同 return HashCode.Combine( Math.Round(obj.Latitude, 9), Math.Round(obj.Longitude, 9) ); } }
使用时的代码会更简洁:
var positionComparer = new PositionEqualityComparer(); listCurrentPostsMarkers.RemoveAll(x => listRemoveMarkers.Any(y => positionComparer.Equals(y.Position, x.Position)) );
内容的提问来源于stack exchange,提问作者fine line
相关产品推荐
相关产品推荐

