Currently I'm working with a lot of classes and lists of those classes. Previously I had static methods which would take a particular list of classes and return a subset or single item of the list.
However I thought it would be more convenient to have classes that inherit List and have the necessary methods there and no longer make them static, so they apply with whatever list of objects you are using.
I have been unable to find a simple way to convert a List to my class that inherits this, so I created a method in all of these collection classes to convert it for me.
Example:
public class Student
{
public int Id {get;set;}
public string Name {get;set;}
}
public class Students : List<Student>
{
public Student GetTopStudent()
{
return this.OrderByDescending(s => s.Grade).FirstOrDefault();
}
public Students GetPassingStudents()
{
return this.Where(s => s.Grade > 0.7).ToCollection();
}
public Students ToCollection(IEnumerable<Student> studentsList)
{
var students = new Students();
foreach(var s in studentsList)
{
students.Add(s);
}
return students();
]
}
I have many other classes and lists of classes like this, but thats a pretty simple example. I'm finding some of my methods, like the "ToCollection()" method are virtually identical, between classes, with the exception of the return type and the type contained in the list.
So I've tried to create extensions and interfaces take care of these methods automatically.
Collection Class and Interfaces
public abstract class Collection<T> : List<T>
{
// Needed tie in the extension method with the List.Add() Method
public void Add(object item) => base.Add((T)item);
}
public interface IObjectWithId<T>
where T : IObjectWithId<T>
{
int Id {get;set;}
}
public ICollectionItem<C>
where C : Collection<IcollectionItem<C>>
{
}
public ICollectionItemWithId<C,T>
where C : Collection<ICollectionItemWithId<C,T>>
where T : IObjectWithId<T>
{
}
Extensions
public static List<T> Get<T>(this IEnumerable<IobjectWithId<T>> list, List<int> ids)
where T : IObjectWithId<T>
{
return list.Where(i => ids.Contains(i.Id))
.Cast<T>();
.ToList();
}
public static C Get<C, T>(this IEnumerable<IcollectionItemWithId<C, T>> list, List<int> ids)
where C : Collection<ICollectionItemWithId<C, T>>, new()
where T : IObjectWithId<T>
{
return list.Where(i => ids.Contains(i.Id)).ToCollection();
}
public static C ToCollection<C, T>(this IEnumerable<ICollectionItemWithId<C, T>> list)
where C : Collection<ICollectionItemWithId<C, T>>, new()
where T : IObjectWithId<T>
{
var collection = new C();
foreach(var item in list)
{
collection.Add(item);
}
return collection;
}
public static C ToCollection<C>(this IEnumerable<ICollectionItem<C>> list)
where C : Collection<ICollectionItem<C>>, new()
{
var collection = new C();
foreach(var item in list)
{
collection.Add(item);
}
return collection;
}
I've been unable to get this code to work. Normally I get errors after building it, either there is no implicit reference conversion from the student class to the list of students or an error pertaining to boxing.
I'm concerned that my interfaces referencing eachother could be creating a lot of problems, however the reason I do this is so I don't have to specify the return type of a method, although perhaps that would be the easiest thing to do at this point...