views:

91

answers:

4

I have a method:

internal List<int> GetOldDoctorsIDs
{
    var Result = from DataRow doctor in DoctorTable.Rows
                 where doctor.Age > 30
                 select doctor.ID
    List<int> Doctors = new List<int>();
    foreach (int id in Result)
    {
         //Register getting data
         Database.LogAccess("GetOldDoctorsID: " + id.ToString());
         if (Database.AllowAccess(DoctorsTable, id))
         {
             Doctors.Add(id);
         }
    }
}

So this gets old doctors and does other things. Now I would like to create method GetExpensiveDoctors. It will look like this above, but in place of:

where doctor.Age > 30

I will have:

where doctor.Cost > 30000

How to create elegant, object oriented solution for this? Should I use delegate or other thing?

A: 

You can add the where clause selectively, for example:

var Result = from DataRow doctor in DoctorTable.Rows
                 select doctor.ID;
if(getByAge) {
    Result=Result.Where(doctor => doctor.Age>30);
} else {
    Result=Result.Where(doctor => doctor.Cost>30000);
}

where getByAge would be for example a boolean parameter on your method.

EDIT. If you need to parametrize the where clause, something like this should work:

internal List<int> GetOldDoctorsIDs(Func<Doctor, bool> whereClause)
{
    var Result = DoctorTable.Rows.Where(d => whereClause(d)).Select(d => d.ID);
    //etc...
}

then you invoke the method the way helium has said.

Konamiman
Yes, but what if I will have 6 next methods that change only in where part?
tomaszs
When I write DoctorTable.Rows. i dont get by Intellisense Where, so it's not there
tomaszs
And when I do: select DataRow doctor in DoctorTable>Rows where (rows => whereClause(d) select doctor.ID i get error "Cannot convert lambda expression to type bool because it is not a delegate type
tomaszs
A: 

You could parameterize your method so it takes the condition as a function from DataRow to bool.

Than you could call

GetDoctorsIDs(doctor => doctor.Age > 30);

or

GetDoctorsIDs(doctor => doctor.Cost > 30000);
helium
Could you be more descriptive about this solution?
tomaszs
+3  A: 

If you modify your method so that a predicate parameter is included (see below), you can call the method with any filters you need as per helium's examples.

internal List<int> GetDoctorsIDs(Predicate<DataRow> doctorFilter)
{
    var Result = from DataRow doctor in DoctorTable.Rows
                 where doctorFilter(doctor)
                 select doctor.ID
    List<int> Doctors = new List<int>();
    foreach (int id in Result)
    {
         //Register getting data
         Database.LogAccess("GetOldDoctorsID: " + id.ToString());
         if (Database.AllowAccess(DoctorsTable, id))
         {
             Doctors.Add(id);
         }
    }
}
m_arnell
A: 

I've managed to do this in this way:

internal List<int> GetOldDoctorsIDs()
{
    return GetDoctorsIDs((doctor) => doctor.Age > 30);
}

internal List<int> GetExpensiveDoctorsIDs()
{
    return GetDoctorsIDs((doctor) => doctor.Cost > 30000);
}

internal List<int> GetDoctorsIDs(Func<DataRow, bool> Condition)
{
    var Result = from DataRow doctor in DoctorTable.Rows
                 where Condition(doctor)
                 select doctor.ID
    List<int> Doctors = new List<int>();
    foreach (int id in Result)
    {
         //Register getting data
         Database.LogAccess("GetOldDoctorsID: " + id.ToString());
         if (Database.AllowAccess(DoctorsTable, id))
         {
             Doctors.Add(id);
         }
    }
}
tomaszs
That is pretty much what I suggested as Func<T,TReturn> where TReturn is of type bool is equivalent to Predicate<T>.
m_arnell
yes, so i gave you a point too
tomaszs