具有匿名代表的泛型表达了一个lambdas..我想

本文关键字:我想 lambdas 一个 泛型 | 更新日期: 2023-09-27 18:21:43

所以我正在尝试做一些稍微超出我边缘的事情理解。。。以三种不同的方式。让我解释一下我是什么尝试这样做,那么我会得到我缺乏的细节理解。

我有几个字典,其中包含我需要生成的对象报告。他们都是

ConcurrentDictionary< Int64, List< EarningsReportCV>>

其中收入简历是仅包含以下内容的自定义对象属性(自定义视图模型(。

我有三本这样的词典...初始化它们的代码是几乎相同,它们每个都包含不同的简历类。

下面是一个例子:

private void BuildDictForAllEarn( List<EarningsReportCV> list, ConcurrentDictionary<Int64, List<EarningsReportCV>> theDict )
{
    foreach ( EarningsReportCV cv in list )
    {
        if ( theDict.ContainsKey( Convert.ToInt64( cv.Ssn ) ) )
        {
            //append in list already in Dict - EWB
            theDict[ Convert.ToInt64( cv.Ssn ) ].Add( cv );
        }
        else
        {
            //insert inital list into the Dict - EWB
            List<EarningsReportCV> cvList = new List<EarningsReportCV>();
            cvList.Add( cv );
            theDict.AddOrUpdate( Convert.ToInt64( cv.Ssn ), cvList, ( foundkey, oldvalue  => cvList );
        }
    }
}

所有三个词典都由一个字符串键<T>.Ssn

而不是仅使用CV类型复制和粘贴代码改变,我想做一个通用的方法。为此,我需要通过在一个匿名委托中,允许我一般地接受传递在类型 T 中并得到它是 .要用作键的 Ssn 属性。

我用谷歌搜索,思考和阅读,并走到了这一步......

通用:

 private void BuildDict<T>( List<T> list, ConcurrentDictionary<Int64, List<T>> theDict, Func<T, string> getIndexFunc )
 {
     foreach ( T cv in list )
     {
         if ( theDict.ContainsKey( Convert.ToInt64( getIndexFunc( cv ) ) ) )
         {
             //append in list already in Dict - EWB
             theDict[ Convert.ToInt64( getIndexFunc( cv ) ) ].Add( cv );
         }
         else
         {
             //insert inital list into the Dict - EWB
             List<EarningsReportCV> cvList = new List<EarningsReportCV>();
             cvList.Add( cv );
             theDict.AddOrUpdate( Convert.ToInt64( getIndexFunc( cv ) ), cvList, ( foundkey, oldvalue ) => cvList );
         }
     }
 }

我这样称呼

private void BuildDictForAllEarnLAMBDA( List<EarningsReportCV> list, ConcurrentDictionary<Int64, List<EarningsReportCV>> theDict )
{
    BuildDict<EarningsReportCV>( list, theDict, ( T ) => { return T.Ssn; } );// fix this lambda as paramether stuff...- EWB
}

我想我在那里得到了除了 3r d 参数之外的所有东西,我想要作为 lambda 传入以查找 .的 Ssn 属性泛型类型 <T> .

当我编译它时,我得到这些错误。

错误 43 参数 1:无法从"T"转换为 'EFRGPayroll3G.CV.EarningsReportCV' C:''Users''Brown.Ericw''Documents''Visual 演播室 2013''Projects''WindowsService1''WindowsService1''BLL''RazorReportRenderBLL.cs 406 33 WindowsService1
错误 45 参数 2:无法从 'System.Collections.Generic.List<EFRGPayroll3G.CV.EarningsReportCV>''System.Func<long,System.Collections.Generic.List<T>>' C:''Users''Brown.Ericw''Documents''Visual 演播室 2013''Projects''WindowsService1''WindowsService1''BLL''RazorReportRenderBLL.cs 407 81 WindowsService1
错误 46 参数 3:无法从"lambda 表达式"转换为 'System.Func<long,System.Collections.Generic.List<T>,System.Collections.Generic.List<T>>' C:''Users''Brown.Ericw''Documents''Visual 演播室 2013''Projects''WindowsService1''WindowsService1''BLL''RazorReportRenderBLL.cs 407 89 WindowsService1
错误 44 最佳重载方法匹配 'System.Collections.Concurrent.ConcurrentDictionary<long,System.Collections.Generic.List<T>>.AddOrUpdate(long, System.Func<long,System.Collections.Generic.List<T>> System.Func<long,System.Collections.Generic.List<T>, System.Collections.Generic.List<T>>)' 有一些无效的参数 C:''Users''Brown.Ericw''Documents''Visual 演播室 2013''Projects''WindowsService1''WindowsService1''BLL''RazorReportRenderBLL.cs 407 21 WindowsService1
错误 42 最佳重载方法匹配 'System.Collections.Generic.List<EFRGPayroll3G.CV.EarningsReportCV>.Add(EFRGPayroll3G.CV.EarningsReportCV)' 有一些无效的参数 C:''Users''Brown.Ericw''Documents''Visual 演播室 2013''Projects''WindowsService1''WindowsService1''BLL''RazorReportRenderBLL.cs 406 21 WindowsService1

在这一点上,我不再明白发生了什么...我的大脑已经满了...我该怎么做才能将其带到功能代码段中。我正在寻找该做什么,以及我需要摸索什么来解决这个问题,最好的是所有好文章来向我解释它......任何微小的理解点都非常感谢。

具有匿名代表的泛型表达了一个lambdas..我想

List<EarningsReportCV> cvList = new List<EarningsReportCV>();行应该使用 T ,而不是 EarningsReportCV

您使函数泛型,但只是忘记将旧具体类的这两个实例更改为泛型类型。 该方法在该更改后编译。

话虽如此,您可能应该在函数中更改几个问题。

首先,它似乎试图安全地从多个线程调用,但事实并非如此。 在检查密钥是否存在后,可能会在另一个线程中添加或删除密钥,从而导致项目掉落在地板上。

程序的前提是添加一个项目(如果不存在(,如果存在,则更新它。 这正是AddOrUpdate被设计用来原子的。 你应该简单地调用一次,而不是你正在做的事情。 它甚至使代码更简单。

private void BuildDict<T>(List<T> list,
    ConcurrentDictionary<long, List<T>> theDict,
    Func<T, string> getIndexFunc)
{
    foreach (T cv in list)
    {
        theDict.AddOrUpdate(Convert.ToInt64(getIndexFunc(cv)),
            key => new List<T>() { cv },
            (foundkey, oldvalue) =>
            {
                oldvalue.Add(cv);
                return oldvalue;
            });
    }
}

您还可以进行一些其他更改来改进代码。 由于您只迭代list而不做任何其他事情,因此您可以将该参数设为IEnumerable,允许它是列表以外的任何类型的序列。

如果您的程序被设计为从多个线程访问和操作theDict,则内部列表很可能不应该是列表,而应该是设计为从多个线程(例如ConcurrentBag(访问的集合。

由于您接受的委托确实想要一个long,而不是string,这才是它真正应该接受的,而不是接受string并试图转换它。

这为我们提供了:

private void BuildDict<T>(IEnumerable<T> sequence,
    ConcurrentDictionary<long, ConcurrentBag<T>> theDict,
    Func<T, long> keySelector)
{
    foreach (T cv in sequence)
    {
        theDict.AddOrUpdate(keySelector(cv),
            key => new ConcurrentBag<T>() { cv },
            (foundkey, oldvalue) =>
            {
                oldvalue.Add(cv);
                return oldvalue;
            });
    }
}

由于这三个都使用.Ssn因此您不需要访问Func<>。 你需要告诉方法他们都有一个Ssn:

  interface IHasSsn
  {
       string Ssn;
  }
private void BuildDict<T>( List<T> list, 
                           ConcurrentDictionary<Int64, List<T>> theDict)
   where T : IHasSsn
{
    foreach ( T cv in list )
    {
        long ssn = Convert.ToInt64( cv.Ssn );
        if ( theDict.ContainsKey(ssn) )
        {
            theDict[ssn].Add( cv );
        }
        else
        {
            var cvList = new List<T>();
            cvList.Add( cv );
            theDict.AddOrUpdate(ssn, cvList, ( foundkey, oldvalue  => cvList );
        }
    }
}

并确保每个报告简历都实现了IHasSsn