【问题标题】:How to write LINQ query on Generic List如何在通用列表上编写 LINQ 查询
【发布时间】:2015-11-18 04:45:38
【问题描述】:

我有一种情况,我有一个接受泛型类型对象的泛型方法,我想在该对象上编写一个 LINQ 查询。

这是一个例子:

通用方法:

public static void GetNonNonVerifiedPersons<TResult>(Person<TResult> model)
{
      // How To Write LINQ Here to get non verified person      
}

学生班:

public class Student
{
    public int Id { get; set; }

    public string Name { get; set; }

    public bool IsVerified { get; set; }
}

教师班:

public class Teacher
{
    public int Id { get; set; }

    public string Name { get; set; }

    public bool IsVerified { get; set; }
}

人员类别:

public class Person<T>
{
    public List<T> PersonList { get; set; }
}

主类:

// 1. Get Non Verified Students
var persons = new Person<Student>();
var students = new List<Student>()
                    {
                        new Student { Id = 1, Name = "Student_A", IsVerified = true },
                        new Student { Id = 2, Name = "Student_B", IsVerified = false },
                    };
 persons.PersonList = new List<Student>();
persons.PersonList.AddRange(students);
GetNonNonVerifiedPersons(persons);


// 2. Get Non Verified Teachers
var persons2 = new Person<Teacher>();
var teachers = new List<Teacher>()
                    {
                        new Teacher { Id = 1, Name = "Teacher_A", IsVerified = true },
                        new Teacher { Id = 2, Name = "Teacher_B", IsVerified = false },
                        new Teacher { Id = 3, Name = "Teacher_C", IsVerified = false },
                    };
persons2.PersonList = new List<Teacher>();
persons2.PersonList.AddRange(teachers);
GetNonNonVerifiedPersons(persons2);

【问题讨论】:

  • var result = persons.PersonList.Where(x =&gt; !x.IsVerified).ToList();
  • @AbhilashPA:PersonList 包含通用列表。所以它不会工作。

标签: c# linq generics generic-list


【解决方案1】:

您应该使用接口来指定泛型类型的教师和学生的类型。当您使用where 子句时,编译器能够在编译时进行类型检查。

public interface IHuman
{  
    string Name { get; set; }
    bool IsVerified { get; set; }
}

public class Teacher : IHuman
{
    public int Id { get; set; }

    public string Name { get; set; }

    public bool IsVerified { get; set; }
}

public class Student : IHuman
{
    public int Id { get; set; }

    public string Name { get; set; }

    public bool IsVerified { get; set; }
}

然后你的方法应该是这样的。这里我们有where 子句,它说在实现 IHuman 时只接受泛型类型 TResult。

public static IEnumerable<TResult> GetNonNonVerifiedPersons<TResult>(Person<TResult> model) where TResult : IHuman
{
    return model.PersonList.Where(x => !x.IsVerified);
}

更新:我强烈建议您进行重大更改,因为它应该是这样的。

另一种不常见且速度极慢的方法是在运行时检查类型。

public static IEnumerable<TResult> GetNonNonVerifiedPersons<TResult>(Person<TResult> model)
{
    var list = model.PersonList;
    var t = list.FirstOrDefault() as Teacher;
    if (t != null)
    {
        return model.PersonList.Where(x => !(x as Teacher).IsVerified);
    }

    var s = list.FirstOrDefault() as Student;
    if (s != null)
    {
        return model.PersonList.Where(x => !(s as Student).IsVerified);
    }

    return null;
}

【讨论】:

  • 你是对的。但是我现在无法使用界面。会有很大的变化。
  • @user2988458 查看更新,但请注意您应该使用接口或基类。因为你所有的班级(老师和学生)都有一些共同点。 c# 是面向对象的语言,你应该使用它的力量!
  • 非常感谢您的关注(为此+1)。但是有问题我已经发布了一个示例。在现实世界中,我有两个以上的类,它们具有 20 多个属性,而在这些属性中,只有两个属性是常见的。一个是IsVerified,另一个是Name。 :)。所以我想使用反射是唯一的解决方案。
  • @user2988458 哦,没问题的人。只需将IsVerified 用作常用并且仅在界面中写入。看到我刚刚删除了一个;)。只使用共同的属性。
  • 您仍然可以只为这两个属性使用接口。如果其中一些其他属性暗示另一个接口,您甚至可以在一个类中实现多个接口。
【解决方案2】:

也许这可以解决问题:

IList<Person<TResult>> xyz = new List<Person<TResult>>();
var list = xyz.Where(a => a.GetType() == typeof(Student).IsVerified);

我没有在 IDE 中检查它,但这样的东西会起作用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多