Reputation: 2611
I have a List<Doctor> doctors
where Doctor
is an abstract
class.
In the list I have SubClasses such as DoctorJunior
, DoctorSenior
etc.
How can I count the number of occurrences of a particular SubClass.
This works int count = doctors.Count(c => c is DoctorJunior);
however when I place it in a method using Type
as a parameter it does not work.
public int GetOccurences(Type doctorType)
{
// return Passengers.OfType<doctorType>().Count();
// return doctors.Count(c => c is doctorType)
int count = 0;
foreach (Doctor doc in Doctors)
{
if (doc is doctorType)
{
count++;
}
}
return count;
}
The parameter doctorType
cannot be found.
Why is the parameter doctorType
not found and how can I make a generic method to count types?
Thanks
Upvotes: 2
Views: 660
Reputation: 13676
The reason why it's not working is that is
operator is used only when you compare instance of type with type itself. You can use doc.GetType()
instead and compare this type with type that is stored in doctorType
:
public int GetOccurences(Type doctorType)
{
int count = 0;
foreach (Doctor doc in Doctors)
if (doc.GetType() == doctorType) count++;
return count;
}
Or use LINQ :
public int GetOccurences(Type doctorType)
{
return Doctors.Count(d => d.GetType() == doctorType);
}
You can even use Convert.ChangeType(obj, type);
to count however it's not recommended :
static int GetOccurences(IEnumerable<object> collection, Type t)
{
return collection.Count(item => { try { Convert.ChangeType(item, t); return true; } catch { return false; } });
}
Or Generic approach :
static int GetOccurences<T>(IEnumerable<object> collection)
{
return collection.Count(item => item is T);
}
P.S.
It worth noting that your custom class such as DoctorJunior
is type (defined by You) but not a System.Type
.
System.Type is a class that works with types.
A. Correct
if(c is DoctorJunior) ...
is
operator here with class instance on the left side and class name on the right (not instance of class System.Type
)B. Incorrect
Type t = typeof(DoctorJunior);
if(c is t) ...
System.Type
using is
operator. This is not valid since is
operator doesn't work this way. It only allows to compare instance of class on left side and type name on right for example if(myVariable is Int32 / string / MyClass / ...)
Upvotes: 2
Reputation: 2837
Operator is
doesn't expect variable of type System.Type
on the right side. So, you get an exception. Valid using of is
operator in your case only can be something like doc is DoctorJunior
To make your method work, you can use following code:
public int GetOccurences(Type doctorType)
{
return doctors.Count(c => c.GetType() == doctorType);
}
Upvotes: 0
Reputation: 136134
You could make it a generic method, whereby generic constraints could give you some additional type safety (constrain the type argument to subclasses of Doctor
)
public int GetOccurences<TDoctor>() where TDoctor:Doctor
{
...
if (doc is TDoctor)
...
}
Incidentally, this works well with your both your commented out lines
return Passengers.OfType<TDoctor>().Count();
// or
return doctors.Count(c => c is TDoctor);
or stick with what you've got and use GetType()
(but there is no type safety, I could easily pass typeof(int)
, for example)
public int GetOccurences(Type doctorType)
{
...
if (doc.GetType() == doctorType)
...
}
Upvotes: 0