我正在抽象一些代码,并遇到了将Func的结果转换为整数以进行比较的问题。
我有一个功能:
public static IConvertible GetIllnessRateByParity(IEnumerable<ILLNESS_OBJECT> pItems, int pParity, Func<ILLNESS_OBJECT, IConvertible> pSelector)
{
var filtered = pItems.Where(a => a.Parity == pParity);
return Math.Round(filtered.Count(a => Convert.ToInt32(pSelector(a)) == 1) / (double)GetBirthCountByParity(pItems, pParity), 2);
}
public class ILLNESS_OBJECT
{
public int ID { get; set; }
public DateTime Day { get; set; }
public int Parity { get; set; }
public int Afterbirth { get; set; }
public int OvaryInfection { get; set; }
etc...
}
计算一组数据中特定疾病的发生率。要分析的疾病通过选择器输入,该选择器从ILLNESS_OBJECT对象中选择IConvertible值。
我这样称呼方法:
GetIllnessRateByParity(data, 1, a => a.AfterBirth)
数据是具有非空值的IEnumerable。
该方法在Convert.ToInt32(pSelector(a))部分抛出InvalidCastException而没有明确指出此强制转换失败的原因,是否有人可以向我解释?我的印象是pSelector(a)返回一个与int转换兼容的IConvertible值,对吧?任何帮助将不胜感激!
编辑:异常消息: 类型&#39; System.InvalidCastException&#39;的例外情况发生在CONFIDENTIAL.CLASS.dll但未在用户代码中处理
消息:指定的演员表无效。
答案 0 :(得分:2)
最后一个参数叫做pSelector,但它实际上并不是一个选择器。
它只是返回一个值(int,float ...),而实际选择是由lab方法中的labmda完成的:
filtered.Count(a => Convert.ToInt32(pSelector(a)) == 1)
因此pSelector将返回某种数据类型的值,然后您依赖于能够将其转换为int32。
但是你只需要将它与1进行比较。鉴于你问题中的信息,你真的不需要int32,你需要一个bool。
那么如果通过将比较结果移动到选择器中的1来重构pSelector成为选择器,该怎么办呢?
public static double GetIllnessRateByParity(IEnumerable<ILLNESS_OBJECT> pItems, int pParity, Func<ILLNESS_OBJECT, bool> pSelector)
{
var filtered = pItems.Where(a => a.Parity == pParity);
return Math.Round(filtered.Count(pSelector) / (double)GetBirthCountByParity(pItems, pParity), 2);
}
GetIllnessRateByParity(data, 1, a => a.AfterBirth==1)
答案 1 :(得分:0)
检查this
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var data = new List<ILLNESS_OBJECT>{
new ILLNESS_OBJECT{ ID = 1, Parity = 1, Day = DateTime.Now, SomeString = "1", Long = 2L},
new ILLNESS_OBJECT{ ID = 2, Parity = 2, Day = DateTime.Now, SomeString = "1", Long = 2L},
new ILLNESS_OBJECT{ ID = 3, Parity = 1, Day = DateTime.Now, SomeString = "2", Long = 1L},
new ILLNESS_OBJECT{ ID = 4, Parity = 1, Day = DateTime.Now, SomeString = "3", Long = 3L},
};
Console.WriteLine(GetIllnessRateByParity(data, 1, x => x.ID));
Console.WriteLine(GetIllnessRateByParity(data, 1, x => int.Parse(x.SomeString)));
Console.WriteLine(GetIllnessRateByParity(data, 1, x => (DateTime.Now - x.Day).Days + 1));
Console.WriteLine(GetIllnessRateByParity(data, 1, x => (int)x.Long));
}
public static IConvertible GetIllnessRateByParity(IEnumerable<ILLNESS_OBJECT> pItems, int pParity, Func<ILLNESS_OBJECT, int> pSelector)
{
var filtered = pItems.Where(a => a.Parity == pParity);
return Math.Round(filtered.Count(a => pSelector(a) == 1)/(double)1, 2);
}
}
public class ILLNESS_OBJECT
{
public int ID { get; set; }
public DateTime Day { get; set; }
public int Parity { get; set; }
public int Afterbirth { get; set; }
public string SomeString { get; set; }
public long Long { get; set; }
}