给定两个不同类型的列表,是否有可能使这些类型相互转换或相互比较(例如使用TypeConverter或类似工具),以便LINQ查询可以比较它们?我在SO上看到过其他类似的问题,但没有一个问题指向使类型彼此之间可转换以解决问题。
收藏类型:
public class Data
{
public int ID { get; set; }
}
public class ViewModel
{
private Data _data;
public ViewModel(Data data)
{
_data = data;
}
}
预期用途:
public void DoMerge(ObservableCollection<ViewModel> destination, IEnumerable<Data> data)
{
// 1. Find items in data that don't already exist in destination
var newData = destination.Except(data);
// ...
}
既然我知道如何比较ViewModel的示例和Data的示例,我应该能够提供一些比较逻辑,然后LINQ将用于.Except()之类的查询,这似乎是合乎逻辑的。这可能吗?
5条答案
按热度按时间fjaof16o1#
我知道这有点晚了,但是使用Func有一个更简单的语法,它消除了对比较器的需要。
所以对于类Foo和Bar的列表
可以运行Linq语句,如
它基本上是上面的一个轻微的变化,但对我来说似乎更干净。
yrwegjxp2#
我假设提供从
Data
到ViewModel
的投影是有问题的,所以我提供了除Jason的解决方案之外的另一个解决方案。Except使用散列集(如果我没记错的话),所以您可以通过创建自己的散列集来获得类似的性能。我还假设当
IDs
相等时,您将Data
对象标识为相等。您可能在方法的其他地方使用“oldData”集合,在这种情况下,您可能希望这样做。要么在你的数据类上实现
IEquatable<Data>
,要么为哈希集创建一个自定义的IEqualityComparer<Data>
:vtwuwzda3#
如果您使用此:
您必须将'data'投影到'destination'中包含的相同类型,但使用下面的代码可以摆脱此限制:
有些人可能会认为,由于使用了HashSet,内存效率低下。但实际上,框架的Except方法正在用一个类似的内部类“Set”(我通过反编译看了一下)做同样的事情。
holgip5t4#
最好的办法是提供一个从
Data
到ViewModel
的投影,这样您就可以说其中
f
将Data
Map到ViewModel
。你也需要一个IEqualityComparer<Data>
。rsl1atfo5#
肮脏的把戏:将两个列表投影到它们的共享ID,执行
Except
,然后使用Join
将结果列表再次投影到原始类型,并将原始列表添加到第一个Select
中删除的其余属性。可能性能不是很好,但对于小列表来说,它会很好。