【问题标题】:Own IEnumerable.First(...) implementation without implicitly captured closure (ReSharper)自己的 IEnumerable.First(...) 实现,没有隐式捕获的闭包(ReSharper)
【发布时间】:2017-06-22 16:49:19
【问题描述】:

我基本上想创建自己的 LINQ .First(item =>...) 和 .Single(item => ...) 实现,仅限对象,它会引发异常,并为日志文件提供有意义的消息:

var items = new List<Item>();
// fill items...
var itemIdToFind = 1234; // not supposed to be constant
var itemFound = items.First(
    i => i.ID==1234,
    () => new NotFoundException("Item " + itemIdToFind + " not found in items"));

实现是这样的:

internal static class MyExtendedLinq
{
    public static T First<T, TEx>(this IEnumerable<T> elements, Func<T, bool> predicate, Func<TEx> notFoundErrorFunc)
        where TEx : Exception
    {
        var firstOnly = elements.Where(predicate).Take(1).ToArray();
        // don't confuse found default value with default due to element not found - not FirstOrDefault!.
        if (firstOnly.Length == 1) 
        {
            return firstOnly[0];
        }
        throw notFoundErrorFunc(); // don't care for null func in example
    }
}

这一直给我来自 ReSharper 的 Implicitly Captured Closure 警告,包括 Exception lambda 和谓词函数。

特别是对于 Func 谓词,我认为与常规 LINQ First(predicate) 实现没有区别,它不会显示此警告。

我不希望常规 First(prediate) 方法中出现无意义的 InvalidOperationExceptions,让人们寻找缺少预期的东西的日子。

【问题讨论】:

  • 老实说,您可能只是想关闭整个警告。它几乎总是会出现误报(就像这里的情况一样),即使代码 将对象的生命周期延长得比需要的更长,也不太可能足够,而且对于足够昂贵的对象,这是一个真正的问题。

标签: c# linq lambda closures


【解决方案1】:

您的情况的不同之处在于您有两个不同的 lambda,每个 lambda 都关闭了 不同的 变量。 Enumerable.First 只有一个 lambda,所以它不能这样做。

现在,您不需要关心这个警告,因为这两个委托都不是长期存在的(甚至都不会超过任何一个变量),所以不存在问题这里。当然,Resharper 无法知道这一点,因此选择警告您,以便您确定这里实际上没有问题。

【讨论】:

    猜你喜欢
    • 2012-10-08
    • 2013-09-22
    • 2013-06-10
    • 1970-01-01
    • 2012-11-17
    • 2016-08-05
    • 2018-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多