我已经实现了一个c#linq表达式,该表达式返回一个可为空的十进制数组。我基本上需要将其传递给接受十进制数组的函数
我遇到错误
无法转换匿名类型十进制? []转换为十进制数组。
var benchMark1Returns = GetViewService<MV_INDEX_PERFORMANCE>()
.Where(x => x.IndexId == benchMark1 && x.PriceDate.Year == year)
.Select(x => new { x.Mtd}).ToArray();
var benchMark2Returns = GetViewService<MV_INDEX_PERFORMANCE>()
.Where(x => x.IndexId == benchMark2 && x.PriceDate.Year == year)
.Select(x => new { x.Mtd }).ToArray();
var compoundReturnsBenchMark1 = CompoundReturns(benchMark1Returns);
接受十进制数组的方法
public static decimal? CompoundReturns(decimal[] rtns)
{
if (rtns.Length == 0)
return null;
return rtns.Aggregate((decimal)1, (acc, val) => acc * (1 + val)) - 1;
}
答案 0 :(得分:3)
首先,您不需要匿名类型的集合:
.Select(x => new { x.Mtd })
您只需要小数:
.Select(x => x.Mtd)
此外,它还告诉您Mtd
是decimal?
,而不是decimal
。前者不能直接转换为后者,因为前者支持后者不支持的值。 (即null
)
因此,当Mtd
为null
时,您将需要定义一个默认值:
.Select(x => x.Mtd ?? 0M)
或更改您的方法以接受decimal?[]
:
public static decimal? CompoundReturns(decimal?[] rtns)
请注意,在最后一种情况下,您还需要更新您的方法以支持null
值。例如,在1
调用中将Aggregate()
的大小写更改为以下类型:
rtns.Aggregate((decimal?)1, (acc, val) => acc * (1 + val)) - 1;
答案 1 :(得分:2)
当调用new { x.Mtd }
时,您正在指示编译器创建一个新的匿名类型,该类型作为单个属性称为Mtd
,其中包含十进制值。自然,这不是decimal[]
,而是MyType[]
。
由于似乎您实际上并没有使用该匿名类型,因此您应该简单地返回十进制值本身,而不是匿名类型:
.Select(x => x.Mtd)
答案 2 :(得分:1)
.Select(x => new { x.Mtd})
创建一个新的匿名对象。您只需要属性值:
.Select(x => x.Mtd)
如果Mtd
可以为空,并且您希望过滤掉空值,请使用以下方法:
.Where(x => x.Mtd != null).Select(x => x.Mtd.Value).ToArray();
答案 3 :(得分:0)
您必须进行两项更改:
首先删除匿名类型。然后选择
.Select( x=> x.Mtd ?? 0);
这将允许您在不更改当前方法的情况下将小数点[]作为参数传递。
否则,您必须这样做:
.Select(x =x.Mtd)
并更改method参数以具有可为空的十进制数组。 希望没事
答案 4 :(得分:0)
除了我之前的评论,即
假设
x.Mtd
是decimal
,则只需删除new {}
,即(x => x.Mtd).ToArray()
但是,更大的问题是您的数据库中实际上不应该包含空值-复合回报图表中一段时间内null
索引性能的后果对于复合收益而言将是灾难性的返回-丢失的数据点会使所有未来的数据点失效。
因此,真正的解决方案是在数据源中找到任何空数据点,并为其提供正确的数据。
然后更改从{p}返回的Dto上Mtd
的数据类型
GetViewService
到
decimal? Mtd
(即不允许null)。
然后,原始代码所需要做的就是删除匿名类投影,即
decimal Mtd