小编Ale*_*i S的帖子

为什么我必须为Func参数显式指定我的类型参数?

我正在编写一个简单的Memoize帮助程序,它允许缓存方法结果,而不是每次都计算它们.但是,当我尝试传入一个方法时Memoize,编译器无法确定类型参数.从我的方法签名中不是很明显吗?有没有解决的办法?

示例代码:

using System;
using System.Collections.Concurrent;

public static class Program
{
    public static Func<T, V> Memoize<T, V>(Func<T, V> f)
    {
        var cache = new ConcurrentDictionary<T, V>();
        return a => cache.GetOrAdd(a, f);
    }

    // This is the method I wish to memoize
    public static int DoIt(string a) => a.Length;        

    static void Main()
    {
        // This line fails to compile (see later for error message)
        var cached1 = Memoize(DoIt);

        // This works, but is ugly (and doesn't scale …
Run Code Online (Sandbox Code Playgroud)

c# generics delegates functional-programming

5
推荐指数
1
解决办法
243
查看次数

多个linq"from"和变量可见性

我试图理解为什么这个linq不编译(fundInvoices不可见):

Dictionary<Fund, IEnumerable<Invoice>> paidfundInvoices;
...
from fundInvoices in paidfundInvoices
from p in fundInvoices.Value
group p by p.VendorId into ps
select new Payment
{
    FundId = fundInvoices.Key.FundId, // ERROR here
    Value = ps.Sum(p => p.Amount)
}
Run Code Online (Sandbox Code Playgroud)

所以我继续将其更改为匿名类型用法,并且基金发票在这里神奇可见:

from fundInvoices in paidfundInvoices
select new
{
    Fund = fundInvoices.Key,
    Payments = from p in fundInvoices.Value
               group p by p.VendorId into ps
               select new Payment
               {
                   FundId = fundInvoices.Key.FundId,  // NO ERROR                                                                                                                                    
                   Value = ps.Sum(p => p.Amount)
               }
};
Run Code Online (Sandbox Code Playgroud)

但是这种匿名类型似乎是多余的,我没有使用它.我只需要一个 …

c# linq grouping

3
推荐指数
1
解决办法
294
查看次数

您更喜欢“具体化”IEnumerables?

有时有必要在方法中间实际“评估” IEnumerable,因为它在多个查询中使用,并且编译器会发出警告(“可能的 IEnumerable 多重枚举”)

var skippedIds = objects.Where(x => x.State=="skip")
                .Select(x => x.Id)
                .Distinct();

            var skippedLookup = skippedIds.ToLookup(x => x.FundId, _ => new { _.Id, _.Name});

            if (skippedIds.Any()) // compiler warning
            {
                ...
                // other iterations over skippedIds, etc.
            }
Run Code Online (Sandbox Code Playgroud)

我曾经做过:

var skippedIds = objects.Where(x => x.State=="skip")
                    .Select(x => x.Id)
                    .Distinct()
                    .ToList();
...
Run Code Online (Sandbox Code Playgroud)

但想知道是否有更好的选择。上面的代码List<T>在堆上创建对象,我猜这是在方法内死亡的临时变量的上下文中不必要的 GC 负担。我现在正在使用库ToImmutableArray()自带的System.Collections.Immutable这不仅创建了堆栈分配的对象不是真的,感谢评论者),而且还将“不可变”语义附加到我的代码中,我认为这是一个很好的函数式实践。

但对性能有什么影响呢?“具体化”在方法内本地多个位置使用的临时子查询结果的最佳方式是什么?

c# linq memory performance functional-programming

2
推荐指数
1
解决办法
894
查看次数