0

I searched and searched, and cannot find a solution to something that seems should be easy to do. Here is an example of my classes.

public class Employee
{
    // Some properties
}

public class Employees : List<Employee>
{
}

I use the Employees class to simplify variable declarations, but may also place some other code there, like getting aggregate information, etc.

The problem occurs when I use linq functions on it, usually Where. For example:

Employees employees = csv.LoadEmployees(txtEmployeeMasterFileName.Text);
employees = employees.Where(emp => emp.Status.ToUpper() == "A"); // Only select active employees

I get a compile time error:

Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<Payroll_Migration.Model.Employee>' to 'Payroll_Migration.Model.Employees'. An explicit conversion exists (are you missing a cast?)   

If I add an explicit cast like this:

employees = (Employees)employees.Where(emp => emp.Status.ToUpper() == "A");

I get a runtime error:

Unable to cast object of type 'WhereListIterator`1[Payroll_Migration.Model.Employee]' to type 'Payroll_Migration.Model.Employees'.

Is there any way around this, or do I have to use List instead of Employees?

  • 6
    Why on earth are you deriving from `List`? That class is not meant to be a base class. Use `Collection` if you want to modify any behavior. – Tanveer Badar Nov 15 '19 at 18:35
  • What are you trying to achieve by deriving from `List` class? – Sach Nov 15 '19 at 18:37
  • One reason is that I find declarations like Employees employees; more readable than List employees;, but that's just personal preference. More important reason is that I may need to add functionality in that class that acts upon all employees, i.e. update their earnings / deductions, etc. Yes, I can create a new class and add a property to that new class of type List, but it's just more cumbersome. It feels more intuitive to just extend the List class, because I can access all LINQ functions without having to reference a class member. – Hrayr Galoyan Nov 15 '19 at 23:30
  • Maybe that's not the correct approach, and if that's the case, I would appreciate if you can suggest alternatives. – Hrayr Galoyan Nov 15 '19 at 23:30

2 Answers2

0

I echo others' questions about subclassing from List<T>, but how you could populate the list is to create a new list and fill it from the projection:

newEmployees = new Employees();
newEmployees.AddRange(employees.Where(emp => emp.Status.ToUpper() == "A"));
D Stanley
  • 149,601
  • 11
  • 178
  • 240
0

This is any X-Y Problem, Employees class should not inherit from list. Employees is a class that should contain a list, you aren't extending the list functionality so don't inherit from it. If you want to read more about it you can here

If you really want to create a container class it should look more like this:

public class EmployeesDTO
{
    List<Employee> NewEmployees { get; set; }
}

var employees = new EmployeesDTO(); 
employees.NewEmployees = csv.LoadEmployees(txtEmployeeMasterFileName.Text)
     .Where(emp => emp.Status.ToUpper() == "A")
     .ToList();

But chances are even this is still an X-Y Problem. Chances are you don't need a EmployeeDTO at all, you just want to be operating on a list of employees.

so you should just be doing:

var newEmployees = csv.LoadEmployees(txtEmployeeMasterFileName.Text)
    .Where(emp => emp.Status.ToUpper() == "A")
    .ToList();

and where ever you were passing your Employees class you should just pass a IEnumerable<Employee>.

johnny 5
  • 19,893
  • 50
  • 121
  • 195
  • Thanks for the comment. Yes, it can be done by creating a new class (EmployeesDT0 in your example) and adding the list of employees as a property, but it just doesn't look as elegant as subclassing the list itself, because now I have to reference the NewEmployees property of the class for every operation... – Hrayr Galoyan Nov 15 '19 at 23:32
  • It seems all the functionality that I need is already available in the List class. Feels like I must be missing something small to make the type conversion work... – Hrayr Galoyan Nov 15 '19 at 23:34