C#将System.Func <tderived,bool =“”>转换为System / Func <tbase,bool =“”>

时间:2017-02-15 15:13:33

标签: c# linq func derived

我用Google搜索但无法找到满意的答案。我基本上试图让这段代码起作用:

public List<WordEntry> WordDataBase = new List<WordEntry>();
public List<CharacterEntry> CharacterDataBase = new List<CharacterEntry>();

public List<Entry> SelectWhere<T>(System.Func<T, bool> predicate) where T : Entry
{
    if (typeof(T) == typeof(WordEntry))
        return WordDataBase.Where(predicate);
    else if (typeof(T) == typeof(CharacterEntry))
        return CharacterDataBase.Where(predicate);
    else
        return null;
} 

在此示例中,WordEntry和CharacterEntry都是从Entry派生的。我得到编译器错误:

Error   CS1503  Argument 2: cannot convert from 'System.Func<T, bool>' to 'System.Func<WordEntry, int, bool>'   

Error   CS1503  Argument 2: cannot convert from 'System.Func<T, bool>' to 'System.Func<CharacterEntry, int, bool>'

希望你能帮助我。提前致谢

3 个答案:

答案 0 :(得分:8)

基本上,你只需要强制转换 - 语言规则不允许编译器在考虑所涉及的类型时考虑if语句。请注意, 还需要调用ToList<Entry>(),指定类型参数以避免获得List<WordEntry>List<CharacterEntry>

public List<Entry> SelectWhere<T>(Func<T, bool> predicate) where T : Entry
{
    if (typeof(T) == typeof(WordEntry))
        return WordDataBase
            .Where((Func<WordEntry, bool>) predicate)
            .ToList<Entry>();
    else if (typeof(T) == typeof(CharacterEntry))
        return CharacterDataBase
            .Where((Func<CharacterEntry, bool>) predicate)
            .ToList<Entry>();
    else
        return null;
}

我建议不要将其设为通用,而是可能只想使用两种不同的方法。鉴于它只适用于两种非常特殊的类型,它并不觉得它真的是一种通用方法。

答案 1 :(得分:4)

你的方法SelectWhere根据参数的类型做了不同的事情 - 所以为什么不使用重载方法

public List<WordEntry> SelectWhere(Func<WordEntry, bool> predicate)
{
    return WordDataBase.Where(predicate);
} 

public List<CharacterEntry> SelectWhere(Func<CharacterEntry, bool> predicate)
{
    return CharacterDataBase.Where(predicate);
}

然后你可以使用那些方法而无需强制转换和“可怕的”if...else语句

Func<WordEntry, bool> isValid = word => word.SomeProperty > 0;
var filteredWords = SelectWhere(isValid); // WordDataBase will be used

Func<CharacterEntry, bool> IsValid = character => character.SomeProperty != null;
var filteredCharacters = SelectWhere(IsValid); //CharacterDataBase will be used

答案 2 :(得分:0)

根据你所显示的错误,我认为你的谓词有错误的声明。

数据库对象的where子句需要Func<T, int, bool>,请注意第二个参数 int ,因此更改此类扩展方法应该是正确方向的进展

public List<Entry> SelectWhere<T>(Func<T, int, bool> predicate) where T : Entry

注意:您已经声明了通用方法,其中您的代码依赖于泛型类型,这使代码以某种方式不那么通用,请检查@Fabio答案我认为他有创建单独的扩展方法的意义。