Well, about the Generics first.
They are useful, because they are able to decouple a concept/algorithm/datatype from its implementation.
Take
Lists
, for instance. It doesn't matter what type of object that list holds, iterating through its elements will always use the same algorithm.
For instance, let's say you have you have 2 lists: one of strings,
List<string> lotsOfStrings = new List<string>()</string></string>
and one of custom objects
List<client> clients = new List<client>()</client></client>
;
Then, you can iterate through each of them in (roughly) the same way:
foreach(Client client in clients)
{
}
and
foreach(string data in lotsOfStrings)
{
}
Lists are one of the most used data structures in real-life projects (to be honest, I can't rememeber any project I've worked on professionally where I hadn't have to use a List,
or an analog data structure). They help a lot in grouping, iterating and performing bulk operations (mostly with LINQ) on objects of the same type, no matter what that type would be.
There are also lots of other uses for Generics, the example I've given you is just a basic tip-of-the iceberg explanation, by no means comprehensive. You can sift through CP articles, there are quite a few of them that detail generic using with examples.
On delegates though, I can only give a rough explanation, because what work I've had to do with them was pretty simple and straightforward. You might wanna check
this article[
^] for a beginner's guide with examples on delegates though.
Happy coding!