[英]Generics wtih anonymous Delegates expressed a lambdas… Ithink
因此,我正在尝试以三种不同的方式做一些超出我的理解范围的事情。 让我解释一下我要做什么,然后我将了解我缺乏理解的细节。
我有几个词典,其中包含生成报告所需的对象。 他们都是
ConcurrentDictionary< Int64, List< EarningsReportCV>>
其中收益CV是仅包含属性的自定义对象(自定义视图模型)。
我有三个这样的字典...并且初始化它们的代码几乎是相同的,它们每个都包含一个不同的CV类。
这是一个例子:
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传递来查找通用类型<T>
的.Ssn属性。
编译时,出现这些错误。
错误43参数1:无法从'T'转换为'EFRGPayroll3G.CV.EarningsReportCV'C:\\ Users \\ Brown.Ericw \\ Documents \\ Visual Studio 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 Studio 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 Studio 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 Studio 2013 \\ Projects \\ WindowsService1 \\ WindowsService1 \\ BLL \\ RazorReportRenderBLL.cs 407 21 WindowsService1
错误'System.Collections.Generic.List<EFRGPayroll3G.CV.EarningsReportCV>.Add(EFRGPayroll3G.CV.EarningsReportCV)'
的最佳重载方法匹配具有一些无效的参数C:\\ Users \\ Brown.Ericw \\ Documents \\ Visual Studio 2013 \\ Projects \\ WindowsService1 \\ WindowsService1 \\ BLL \\ RazorReportRenderBLL.cs 406 21 WindowsService1
到那时我再也无法理解发生了什么...我的大脑已经满了...我该怎么做才能将其带入功能代码中。 我正在寻找要做的事,也需要寻找什么,需要把我的头裹在这件事上,并且在所有最好的文章中向我解释一下。...
行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 );
}
}
}
并确保每个ReportCV都实现IHasSsn
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.