Note: the definition of the 'Student class, and the List<Student> 'studentList, used here is appended below.
Suppose we want a query function that, given a list of values-to-match, returns all instances of 'Student in the 'studentList which, for fields that are of Type List<>, have any of the values-to-match ?
Func<Student, List<int>, bool> MatchFromScoresList = (student, itemList)
=> student.Scores.Any(isMatchingEntry => itemList.Contains(isMatchingEntry));
Func<Student, List<string>, bool> MatchFromCommentsList = (student, itemList)
=> (student.Comments != null) && student.Comments.Any(isMatchingEntry
=> itemList.Contains(isMatchingEntry)); Okay, now we can use queries like:
var test1 = students.Where(student => MatchFromScoresList(student, new List<int>{60,91}));
var test2 = students.Where(student => MatchFromCommentsList(student, new List<string> { "one", "two"})); Question 1: is there any value to writing these function calls using the static 'Where of 'Enumerable ?
var test1 = Enumerable.Where(students, student
=> MatchFromScoresList(student, new List<int>{60,91})); Question 2: Suppose we wanted to define one Func to handle both matching Lists of Types Int, and String ? Yes: this is an intellectual exercise, probably unnecessary excursion into the impractical and esoteric ... until you tell me it's not ! In fact, I suspect using dynamic in a Func is not a good practice, and would lead to impaired performance, and, since it's easy to chain multiple Linq calls and do 'Joins ... well ... I still want to know
Clearly we can pass use a 'dynamic variable in the Func to get whatever Type of values-to-check List we want into the Func: these will work fine with the same two sample calls shown above:
Func<Student, dynamic, bool> dynMatchFromScoresList = (student, itemList)
=> student.Scores.Any(isMatchingEntry => itemList.Contains);
Func<Student, dynamic, bool> dynMatchFromCommentsList = (student, itemList)
=> (student.Comments != null) && student.Comments.Any(isMatchingEntry
=> itemList.Contains(isMatchingEntry)); But, how we could pass something into the Func that would tell it which Field in the data to compare to: Student.Scores, or Student.Comments ? The only way I can see to do that now is to use a boolean flag:
Func<Student, dynamic, bool, bool> dynMatchFromMultiTypeList = (student, itemList, isListType) =>
(isListType)
?
(student.Comments != null) && student.Comments.Any(isMatchingEntry
=> itemList.Contains(isMatchingEntry))
:
(student.Comments != null) && student.Comments.Any(isMatchingEntry
=> itemList.Contains(isMatchingEntry));
var test0 = Enumerable.Where(students, student => dynMatchFromMultiTypeList(student, new List<int> { 88, 91 }, true)); Is it possible to do some kind of Type checking in the body of the Func: perhaps you can enlighten me, thanks !
public class Student
{
public string First { get; set; }
public string Last { get; set; }
public int ID { get; set; }
public List<int> Scores;
public List<string> Comments;
}
private List<Student> studentList;
// initialization
private void initializeStudentList()
{
// sample data copied from somewhere on one of MSDN's pages on Linq
studentList = new List<Student>
{
new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores= new List<int> {97, 92, 81, 60}, Comments = new List<string>{"one","two"}},
new Student {First="Claire", Last="O’Donnell", ID=112, Scores= new List<int> {75, 84, 91, 39}},
new Student {First="Debra", Last="Garcia", ID=115, Scores= new List<int> {35, 60, 91, 70}},
new Student {First="Fadi", Last="Fakhouri", ID=116, Scores= new List<int> {99, 86, 90, 94}, Comments = new List<string>{"three","two"}},
new Student {First="Hanying", Last="Feng", ID=117, Scores= new List<int> {93, 92, 80, 87}},
new Student {First="Michael", Last="Tucker", ID=122, Scores= new List<int> {94, 92, 91, 91} }
};
}
« There is only one difference between a madman and me. The madman thinks he is sane. I know I am mad. » Salvador Dali
modified 21-Oct-14 21:59pm.
|