跨应用程序域边界传递IEnumerable通常是个坏主意吗?
我问,因为我目前对IEnumerable实现的理解,直到集合被枚举后才会使用枚举器。当您跨越appdomain边界,特别是涉及多个进程时,这不会导致跨越边界的多次跳转,每个项目返回一次吗?如果是这种情况,那么在可能的情况下(例如在数组中)完整地返回集合在性能方面会更好,不是吗?
答案 0 :(得分:3)
首先,它取决于枚举对象的方式:是继承自MarshalByRef
还是可序列化。在第二种情况下,副本将传递给另一个appdomain,然后类似于数组方法。另一方面,如果它继承自MarshalByRef
,那么它几乎取决于枚举器如何访问所有者实例。
所以一般来说,如果您确实知道会发生什么,我应该说只应通过IEnumerable
个应用程序域。否则,您可能会收到意外结果或性能不佳。
答案 1 :(得分:2)
实际上,假设MarshalByRefObject
,每件商品的行程 2 (加一);一个到MoveNext()
,一个到Current
(每个MoveNext()
返回true
)。加上GetEnumerator()
来电,可能是Dispose()
。所以对于MarshalByRefObject
,不,不要这样做;使用数组。
但是,如果不是 MarshalByRefObject
,那就更有趣了。例如,ADO.NET数据服务公开LINQ API(IQueryable<T> : IEnumerable<T>
)上的数据,但这可以通过在需要时构建特定查询,进行一次往返并在客户端迭代来实现。
当然,您可能不应该在任何真实距离上使用远程(更喜欢WCF等),因此第一种情况可能不是巨大的问题 - 你不会有多少延迟。此外,您将在实体上遇到相同的延迟问题(如果MarshalByRefObject
)或序列化成本(如果没有)。
就个人而言,在极少数场合我使用远程处理(通常只是为了允许dll卸载),我有一个MarshalByRefObject
代表某种服务和可序列化的实体对象。也许对我来说可能是可以预见的,我使用protobuf-net来最小化序列化成本。
答案 2 :(得分:1)
是的,这是一个坏主意。枚举器几乎总是保持对它所枚举的集合的引用。假设两者都是可序列化的,那么当您越过边界时,您也会序列化整个集合。不过往返。
答案 3 :(得分:0)
耶。即使将它传递给线程也不安全。你最好把它转换成数组来传递。