【发布时间】:2014-01-08 05:55:19
【问题描述】:
我有一个或多或少看起来像这样的方法:
ConcreteType Find(IEnumerable<ConcreteType> values)
它迭代 IEnumerable 并在某些时候返回结果中包含的值之一。此方法不受我控制,我无法更改。
我需要将此方法包装在另一个应该如下所示的方法中:
T Find(IEnumerable<T> values, Func<T,ConcreteType> map)
有一个泛型类型T。此方法应调用上述方法,将所有值从T 映射到ConcreteType,然后将返回的ConcreteType 映射回原始T。
最简单的方法是什么?
重要提示: 可枚举是动态评估的 (LINQ),map 方法可能很慢。因此,该解决方案不允许迭代可枚举的次数超过原始 Find 必须做的事情,并且也应该只为原始 Find 方法实际请求的值调用 map 方法。
您可以假设所有值(T 或 ConcreteType)都是唯一的,因此不可能将一个 ConcreteType 映射到各种 T,反之亦然。
示例:
如果上面说的太抽象,这里举个具体的例子:
// Original method
byte[] FindMatchingBuffer(IEnumerable<byte[]> values)
// Wrapper (TODO)
T FindMatchingBuffer(IEnumerable<T> values, Func<T, byte[]> map)
// Sample call
string matchingFileName = FindMatchingBuffer(fileNames, File.ReadAllBytes);
谢谢!
【问题讨论】:
-
你能保证你不能改变的方法只会迭代到它需要的地方吗?换句话说,你能返回它获取的最后一个值吗?
-
@JonSkeet 我知道该方法只会根据需要进行迭代。所以,是的,我可以返回最后一个捕获的值。虽然我认为这样的解决方案对我来说有点肮脏......
-
我会说,你天生就处于一个肮脏的境地。您是否有任何保证可以比较
ConcreteType的实例是否相等?将ConcreteType的所有映射实例存储在内存中是否有问题?在您给出的示例中,这两者都很痛苦 - 您可能不想保留您读取的所有文件的所有数据。 -
是的,我知道 ConcreteType 的实例,因为我自己“生产”它们,并且该方法的假定“合同”是它总是返回列表中的一个项目或 null。具体类型都是不同的,可以通过引用进行比较。无需按值比较。
-
另外,虽然必须将数据保存在内存中并不好,但这不会成为问题,因为所有值的完整总和预计会小于几兆字节,我已经无论如何都要缓存其中一些值,因为加载它们很昂贵。
标签: c# .net linq generics functional-programming