I am by no means very well versed in this matter, but from my point of view it was useful to allow people to create polymorphic components without first knowing how these components will be consumed. What I mean? Let me try to explain.
Take a simple example with the .NET framework class ArrayList . This was part of the original structure prior to the introduction of Generics. The authors of the ArrayList class tried to provide a useful implementation of a dynamic list, but they had no way of knowing which objects would be inserted into the list. They used the type of the object to represent the elements in the list, since it allowed any type of class to be added to the list. For example:
ArrayList people = new ArrayList(); people.Add(new Doctor()); people.Add(new Lawyer()); people.Add(new PetDetective()); people.Add(new Ferrari()); // Yikes! // ... for (int i = 0; i < people.Count; i++) { object person = people[0]; // ... }
Now, if this was your own application, and you knew that your Doctor , Lawyer and PetDetective all derived from the common base Person class, then you could theoretically build your own linked list based on the Person class, not the Object class. However, there is a lot of extra work for very little use when you already have the built-in and tested ArrayList class. If you really want to make it specific to your base Person class, then you can always create a wrapper class for ArrayList that accepts only Person measurable objects.
In C ++, you can do almost the same thing using the data type "void pointer" ( void* ). However, C ++ also supported templates (very similar to generics), which greatly simplified the collection of a useful component, not knowing the details of what other classes it will be used with. Since C # did not support generators at first, using the Object type was really the only way to create common polymorphic components for other people.
Dr. Wily's apprentice
source share