Let us suppose you have 20 different classes and you want to compare name property for each class then it would become combersome process. You will have to create 20 separate NameComparee classes. The question is how to create just one class and get comparison task done. You can solve this problem by creating a generic class implementing the generic interface, IComparer<T>.
Example of Generic class Implementing a generic interface IComparerclass DoctorNameComparer : IComparer<Doctor>
{
public int Compare(Doctor? x, Doctor? y)
{
if (x == null || y == null)
{
throw new ArgumentNullException("Name of doctor is missing");
}
return string.Compare(x.Name, y.Name, StringComparison.OrdinalIgnoreCase);
}
}class Doctor
{
public Doctor(string name, int age)
{
Name = name;
Age = age;
}
public string Name { get; }
public int Age { get; }
}class Engineer
{
public Engineer(string name, int age)
{
Name = name;
Age = age;
}
public string Name { get; }
public int Age { get; }
}class EngineerNameComparer : IComparer<Engineer>
{
public int Compare(Engineer? x, Engineer? y)
{
if (x == null || y == null)
{
throw new ArgumentNullException("Name of Engineer is missing");
}
return string.Compare(x.Name, y.Name, StringComparison.OrdinalIgnoreCase);
}
}
Create one generic comparer and pass a function that selects the property to compare:
- Create PropertyComparer<T> class which implements IComparer<T>.
- Func delegate is constructor parameter of PropertyComparer<T> class. The Func delegate will take type T and will return property from type T.
- Here, Func Delegate will take an object and will return property of that object.
- Constructor is used to create delegate object in PropertyComparer class.
class PropertyComparer<T> : IComparer<T>
{
private readonly Func<T, string> _selector;
public PropertyComparer(Func<T, string> selector)
{
_selector = selector; // delegate initialized
}
public int Compare(T? x, T? y)
{
if (x == null || y == null)
throw new ArgumentNullException();
return string.Compare(
_selector(x), // delegate invoked
_selector(y), // delegate invoked.
StringComparison.OrdinalIgnoreCase);
}
}In Main method:Doctor[] doctors =
{
new Doctor("Raj", 40),
new Doctor("Amit", 35)
};
Engineer[] engineers =
{
new Engineer("Vikas", 30),
new Engineer("Anil", 25)
};
Array.Sort(doctors, new PropertyComparer<Doctor>(d => d.Name));
Array.Sort(engineers, new PropertyComparer<Engineer>(e => e.Name));
Common Interface for all classes
In Main method
interface IHasName
{
string Name { get; }
}
class Doctor : IHasName
{
public Doctor(string name, int age)
{
Name = name;
Age = age;
}
public string Name { get; }
public int Age { get; }
}
class Engineer : IHasName
{
public Engineer(string name, int age)
{
Name = name;
Age = age;
}
public string Name { get; }
public int Age { get; }
}Create a common generic comparer with constraint
class NameComparer<T> : IComparer<T>
where T : IHasName
{
public int Compare(T? x, T? y)
{
if (x == null || y == null)
throw new ArgumentNullException();
return string.Compare(
x.Name,
y.Name,
StringComparison.OrdinalIgnoreCase);
}
}
Array.Sort(doctors, new NameComparer<Doctor>());
Array.Sort(engineers, new NameComparer<Engineer>());
No comments:
Post a Comment