Samuel R. Neff said:
The IClonable interface is needed when you want to provide clonable
functionality for a bunch of classes and don't care what actually
implements the class.
Say you have:
class A : IClonable {
public object Clone() { ... }
}
class B : IClonable {
public object Clone() { ... }
}
and then you had an object array
object[] array1 = new object[] { new A(), new B() };
you can clone the array like this:
object[] array2 = new object[array1.length];
for(int i=0; i<array1.length; i++) {
array2 = ((IClonable)array1).Clone();
}
There you've provided clonability for an object even though the
calling code doesn't care what class it is--only that it implements
IClonable.
Andrew Troelsen has 14 books on Amazon so I don't know exactly which
book you're referring to. However, I have one of his books, C# and
the .NET Platform (second edition) in front of me and look at Chapter
6: Interfaces and Collections he has a section on "Building a custom
Enumerator (IEnumerable and IEnumerator). What he writes in this
section is wrong and a horrible example of how to do what he's
explaining.
First he says that if you try to use foreach on a class that doesn't
have IEnumerable or GetEnumerator, he says that the compiler will
complain 'cause the class "does not implement the GetEnumerator()
method." This is correct. However, he goes on to say that
GetEnumerator() is defined in IEnumerable and we can add
GetEnumerator() to our class by making our class implement
IEnumerable.
This is literally correct but the implication is wrong. IEnumerable
does provide the declaration of GetEnumerator() and if you're
implementing GetEnumerator() then you should always implement
IEnumerable in order to conform with standards and use expectations,
however it isn't technically correct that you need to implement
IEnumerable to use foreach. The compiler looks for GetEnumerator()
method only, it doesn't look for the interface.
Some people may write code that can work on an IEnumerable class or
make custom calls to GetEnumerator() and for that reason you should
always implement IEnumerable when providing a GetEnumerator()
method--but it's not absolutely required (as you found out).
Then he goes on to implement GetEnumerator() by adding custom
enumeration functionality to the Car class itself. NO NO NO, don't
ever do this. If two threads try to enumerate the same collection
they'll overwrite each other's position and create huge problems. If
you try to iterate the same collection twice in a nested loop, it'll
have the same problem. If you change the collection while enumerating
you could end up hitting the same item twice or aborting prematurely
(the enumerator is technically supposed to throw an error at this
point). If you want a good example of how to impelment an enumerator
then get Reflector and look at how it's done in the framework classes.
Don't follow Andrew Troelsen's recommendations.
I also see the same book has a discussion of IClonable with a sample
very similar to the one you showed. I'm sorry to say that the sample
shows what Clone() is supposed to do but it doesn't show why you
implement IClonable. Hopefully the above sample helped to clear
things up for you.
Best regards,
Sam
------------------------------------------------------------
We're hiring! B-Line Medical is seeking Mid/Sr. .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.