什么是使用选择的目的;在间歇法(X =&GT X)? [英] What is the purpose of using Select(x => x) in a Batch method?

查看:99
本文介绍了什么是使用选择的目的;在间歇法(X =&GT X)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在看的源代码批量 方法,我已经看到了这一点:

  / /选择是必要的,这样斗内容流过
收益率的回报resultSelector(bucket.Select(X => X));

有一个评论,我没有听明白。我已经测试这种方法不使用选择,效果不错。但似乎有什么东西我missing.I想不出任何例子,这将是必要的,那么,有什么用实际目的选择(X => X)此处



下面是引用的全部源代码:

 私有静态的IEnumerable< TResult> BatchImpl< TSource,TResult>(
本的IEnumerable< TSource>源,
INT大小,
Func键< IEnumerable的< TSource>中TResult> resultSelector)
{
TSource []桶= NULL;
变种数= 0;

的foreach(源VAR项)
{
如果(斗== NULL)
斗=新TSource【尺寸】;

斗[统计++] =项目;

//它产生
如果之前水桶全缓冲(数=大小!)
继续;

//选择是必要的,这样斗内容流过
收益率的回报resultSelector(bucket.Select(X => X));

桶= NULL;
计数= 0;
}

//返回最后一个桶所有剩余的元素
如果(桶= NULL&放大器;!&放大器;计数大于0)
收益率的回报resultSelector( bucket.Take(计数));
}


解决方案

要总结什么的注释,理论上这是多余的。延迟执行在这种情况下不相关的。在收益满点的执行的已经作出:的已经含量计算并没有什么推迟。



也没有引起迭代器块的行为问题 - 每一个我们回到这个实施时间的正在复位并重新创建(桶= NULL 后,立即收益)。即使有人把结果给数组类型,并修改它,我们不在乎



该方法的优点似乎是唯一的优雅气质:有一个键入 resultSelector 所有通话之间的一致性。没有多余选择,实际类型将是 TSource [] 的大部分时间,而的IEnumerable< TSource方式> 的尾部元素没有填满整个



但是,可以想见以下情形:




  1. 有人使用此功能注意到的实际类型数组

  2. 因为有些冲动,需要提高的表现,他们投接收一批 TSource [] (例如,他们现在可以更有效地跳跃的元素, 跳过是为数组

  3. 他们使用的方法没有任何问题,因为它发生不优化的计数()%的大小== 0 在他们的情况



直到后来,它发生一个额外的元素出现的画面,引起了最后一个收益执行。现在剧组到 TSource [] 将失败。



因此,根据元素的数量和尺寸的方法将行为不一致就其结果类型(通过给定的回调)。可以想见其他复杂的场景中这种不一致会引起麻烦,像一些ORM的是,根据实际类型,序列化对象到不同的表。在这种情况下的数据块会在不同的表中结束。



这些情形,当然所有基于一些其他错误地作出,并且不证明未经选择的实施是错误的。然而,这是更的友好的使用选择,从某种意义上说,它减少了这种不幸的情况下的数量降到最低。


I was looking at the source code of Batch method and I have seen this:

// Select is necessary so bucket contents are streamed too
yield return resultSelector(bucket.Select(x => x));

There is a comment which I didn't quite understand. I have tested this method without using Select and it worked well. But it seems there is something I'm missing.I can't think of any example where this would be necessary, So what's the actual purpose of using Select(x => x) here ?

Here is the full source code for reference:

private static IEnumerable<TResult> BatchImpl<TSource, TResult>(
        this IEnumerable<TSource> source,
        int size,
        Func<IEnumerable<TSource>, TResult> resultSelector)
    {
        TSource[] bucket = null;
        var count = 0;

        foreach (var item in source)
        {
            if (bucket == null)
                bucket = new TSource[size];

            bucket[count++] = item;

            // The bucket is fully buffered before it's yielded
            if (count != size)
                continue;

            // Select is necessary so bucket contents are streamed too
            yield return resultSelector(bucket.Select(x => x));

            bucket = null;
            count = 0;
        }

        // Return the last bucket with all remaining elements
        if (bucket != null && count > 0)
            yield return resultSelector(bucket.Take(count));
    }

解决方案

To sum up what's in the comments, theoretically this is redundant. Deferred execution is irrelevant in this case. At the point of yield full execution has already been made: contents of bucket are already calculated and there is nothing to defer.

There is also no problem caused by the iterator block behaviour - each time we're back in this implementation the bucket is being reset and recreated (bucket = null immediately after yield). Even if someone would cast the result to the array type and modify it, we don't care.

An advantage of this approach seems to be only elegance: there is a type consistency between all calls to resultSelector. Without the "redundant" Select, the actual type would have been TSource[] most of the time, and IEnumerable<TSource> for the trailing elements that did not fill the whole bucket.

However, one can imagine the following scenario:

  1. someone using this function notices that the actual type is an array
  2. because of some urge need to improve performance, they cast the received batch to TSource[] (e.g. they can now skip elements more efficiently, as Skip is not optimized for arrays)
  3. they use the method without any problems, because it happens that Count() % size == 0 in their case

Until, later, it happens that one additional elements pops in, causing the last yield to be executed. And now the cast to TSource[] will fail.

So, depending on the number of elements and size the method would behave inconsistently with regard to its result type (passed to the given callback). One can imagine other elaborate scenarios where this inconsistency can cause trouble, like some ORM that, depending on the actual type, serializes objects into different tables. In this context pieces of data would end up in different tables.

These scenarios are of course all based on some other mistake being made, and do not prove that without the Select the implementation is wrong. It is however more friendly with the Select, in a sense, that it reduces the number of such unfortunate scenarios to a minimum.

这篇关于什么是使用选择的目的;在间歇法(X =&GT X)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆