C# 转换Func的结果<;T、 IConvertible>;在lambda表达式中使用int

C# 转换Func的结果<;T、 IConvertible>;在lambda表达式中使用int,c#,linq,generics,casting,functional-programming,C#,Linq,Generics,Casting,Functional Programming,我正在抽象一些代码,遇到了一个问题,将Func的结果转换为整数进行比较 我有一个功能: public static IConvertible GetIllnessRateByParity(IEnumerable<ILLNESS_OBJECT> pItems, int pParity, Func<ILLNESS_OBJECT, IConvertible> pSelector) { var filtered = pItems.Where(a =>

我正在抽象一些代码,遇到了一个问题,将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...
}
数据是具有非空值的IEnumerable


该方法在Convert.ToInt32(pSelector(a))部分抛出InvalidCastException,但没有明确说明此转换失败的原因,有人能向我解释一下吗?我的印象是pSelector(a)返回一个与int兼容的IConvertible值,对吗?任何帮助都将不胜感激

编辑:异常消息: 机密.CLASS.dll中发生“System.InvalidCastException”类型的异常,但未在用户代码中处理

消息:指定的强制转换无效。

检查

使用系统;
使用System.Collections.Generic;
使用System.Linq;
公共课程
{
公共静态void Main()
{
var数据=新列表{
新对象{ID=1,奇偶校验=1,Day=DateTime。现在,SomeString=“1”,Long=2L},
新对象{ID=2,奇偶校验=2,Day=DateTime。现在,SomeString=“1”,Long=2L},
新对象{ID=3,奇偶校验=1,Day=DateTime。现在,SomeString=“2”,Long=1L},
新对象{ID=4,奇偶校验=1,Day=DateTime。现在,SomeString=“3”,Long=3L},
};
WriteLine(GetIllnessRateByParity(data,1,x=>x.ID));
WriteLine(GetIllnessRateByParity(data,1,x=>int.Parse(x.SomeString));
WriteLine(GetIllnessRateByParity(数据,1,x=>(DateTime.Now-x.Day).Days+1));
WriteLine(GetIllnessRateByParity(data,1,x=>(int)x.Long));
}
公共静态IConvertible GetIllnessRateByParity(IEnumerable pItems,int-pParity,Func pSelector)
{
var filtered=pItems.Where(a=>a.Parity==pParity);
返回Math.Round(filtered.Count(a=>pSelector(a)==1)/(double)1,2);
}
}
公共类对象
{
公共int ID{get;set;}
公共日期时间日{get;set;}
公共整数奇偶校验{get;set;}
公共整数胞后{get;set;}
公共字符串SomeString{get;set;}
公共长{get;set;}
}

最后一个参数称为pSelector,但它实际上不是选择器

它只是返回一个值(int,float…),实际的选择由labmda在Count方法中完成:

filtered.Count(a => Convert.ToInt32(pSelector(a)) == 1)
所以pSelector将返回某个数据类型的值,然后您将依赖于能够将其转换为int32

但是你只需要把它和1比较一下。根据你问题中的信息,你其实不需要int32,你需要一个bool

那么,如果您将pSelector重构为选择器,将比较移到选择器中的1,会怎么样呢

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)
公共静态双GetIllnessRateByParity(IEnumerable pItems、int pParity、Func pSelector)
{
var filtered=pItems.Where(a=>a.Parity==pParity);
返回Math.Round(filtered.Count(pSelector)/(double)GetBirthCountByParity(pItems,pParity),2);
}
GetIllnessRateByParity(数据,1,a=>a.AfterBirth==1)

异常中没有任何额外信息吗?异常的消息是什么?您是否检查了pSelector返回的IConvertible的具体实现?是否可能是不支持ToInt32/的实现在那里抛出了异常?“我的印象是pSelector(a)返回一个与int兼容的IConvertible值”-我不认为是这种情况,但我也不认为这很重要。正在发生的事情是,它正在调用以下重载
to int32
:然后按照Jeroen所说的做。为什么不将
Func pSelector
更改为
Func pSelector
?Convert.ToInt32没有重载需要IConvertable,这就是为什么运行时会退回到调用重载@Chris。你也用函数式编程来标记这个问题,但是你使用的接口更多的是面向对象的,而不是函数式的,Roman的想法更实用。你的类有可变字段。我认为比较是一个实现细节,所以我把它移到了方法中,我同意你对我的命名方案的反馈,谢谢!经过考虑,我将接受您的答案,这种方式不需要困难的转换,并且使方法比选择器更灵活
filtered.Count(a => Convert.ToInt32(pSelector(a)) == 1)
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)