Click here to Skip to main content
Email Password   helpLost your password?

Introduction

Although the subject of cloning in the real world is controversial, in the .NET world it is still safe to use, or isn�t it?

How many times did you find yourself implementing the ICloneable interface for your class, but every time you do the same code, or you do a specific code for each class. And what about, when you add a new field to the class, and you forgot to update the Clone method for the new field. Believe me, this sort of thing leads to annoying bugs.

This is where my class comes to the rescue. With a little help from the reflection mechanism, I created an abstract class that implements the ICloneable interface with the default behavior. Now you are probably asking yourself: What is the default behavior? Well I�m glad you asked. Default behavior for cloning, is to clone every field in the class by the following algorithm:

  1. For each field in the class, ask if it supports the ICloneable interface.
  2. If the field doesn�t support the ICloneable interface, then the field is set in the regular manner, which means that if this field is a value type, then the value will be copied, but if the field is a reference type, the clone field will be pointing to the same object.
  3. If the field supports the ICloneable interface, we use its Clone method to set it in the clone object.
  4. If the field supports the IEnumerable interface, then we need to check if it supports the IList or the IDictionary interface. If it does, then we iterate the collection, and for each item in the collection we ask if it supports the ICloneable interface.

How to use

All you have to do to make your class support the ICloneable interface, is to derive your class from the BaseObject as follow:

public class MyClass : BaseObject
{
    public string myStr =�test�;
    public int id;
}

public class MyContainer : BaseObject
{
    public string name = �test2�;
    public MyClass[] myArray= new MyClass[5];

    public class MyContainer()
    {
        for(int i=0 ; i<5 ; i++)
        {
             this.myArray[I] = new MyClass();
        }
    }
}

Now in the Main method you can do the following:

static void Main(string[] args)
{
    MyContainer con1 = new MyContainer();
    MyContainer con2 = (MyContainer)con1.Clone();

   con2.myArray[0].id = 5;
}

When inspecting the con2 instance you will see that the MyClass instance in the first index was changed to 5, but the con1 instance remained without changes. So you can see that any field you will add to your class, which support the ICloneable interface will be cloned as well. Furthermore, if the field supports the IList interface or the IDictionary interface, the method will detect it and will loop through all the items and will try to clone them as well.

Implementation

/// <summary>

/// BaseObject class is an abstract class for you to derive from.

/// Every class that will be dirived from this class will support the 

/// Clone method automaticly.
/// The class implements the interface ICloneable and there /// for every object that will be derived
/// from this object will support the ICloneable interface as well. /// </summary> public abstract class BaseObject : ICloneable { /// <summary> /// Clone the object, and returning a reference to a cloned object. /// </summary> /// <returns>Reference to the new cloned /// object.</returns> public object Clone() { //First we create an instance of this specific type. object newObject = Activator.CreateInstance( this.GetType() ); //We get the array of fields for the new type instance. FieldInfo[] fields = newObject.GetType().GetFields(); int i = 0; foreach( FieldInfo fi in this.GetType().GetFields() ) { //We query if the fiels support the ICloneable interface. Type ICloneType = fi.FieldType. GetInterface( "ICloneable" , true ); if( ICloneType != null ) { //Getting the ICloneable interface from the object. ICloneable IClone = (ICloneable)fi.GetValue(this); //We use the clone method to set the new value to the field. fields[i].SetValue( newObject , IClone.Clone() ); } else { // If the field doesn't support the ICloneable // interface then just set it. fields[i].SetValue( newObject , fi.GetValue(this) ); } //Now we check if the object support the //IEnumerable interface, so if it does //we need to enumerate all its items and check if //they support the ICloneable interface. Type IEnumerableType = fi.FieldType.GetInterface ( "IEnumerable" , true ); if( IEnumerableType != null ) { //Get the IEnumerable interface from the field. IEnumerable IEnum = (IEnumerable)fi.GetValue(this); //This version support the IList and the //IDictionary interfaces to iterate on collections. Type IListType = fields[i].FieldType.GetInterface ( "IList" , true ); Type IDicType = fields[i].FieldType.GetInterface ( "IDictionary" , true ); int j = 0; if( IListType != null ) { //Getting the IList interface. IList list = (IList)fields[i].GetValue(newObject); foreach( object obj in IEnum ) { //Checking to see if the current item //support the ICloneable interface. ICloneType = obj.GetType(). GetInterface( "ICloneable" , true ); if( ICloneType != null ) { //If it does support the ICloneable interface, //we use it to set the clone of //the object in the list. ICloneable clone = (ICloneable)obj; list[j] = clone.Clone(); } //NOTE: If the item in the list is not //support the ICloneable interface then in the //cloned list this item will be the same //item as in the original list //(as long as this type is a reference type). j++; } } else if( IDicType != null ) { //Getting the dictionary interface. IDictionary dic = (IDictionary)fields[i]. GetValue(newObject); j = 0; foreach( DictionaryEntry de in IEnum ) { //Checking to see if the item //support the ICloneable interface. ICloneType = de.Value.GetType(). GetInterface( "ICloneable" , true ); if( ICloneType != null ) { ICloneable clone = (ICloneable)de.Value; dic[de.Key] = clone.Clone(); } j++; } } } i++; } return newObject; } }
You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralStack overflow exception
roza_gh
2:26 22 Jun '09  
I use this code for making a clone of my objects but `I got an exception when i run it for my code
The eception is
An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll
what I have to do ? please help me

Generaldid'nt really create new objects with the enumerable types for me : now populate them with cloned objects - properties instead of fields as well
jean.mourmon
4:17 25 Mar '09  
Hi,

This piece of code did'nt really create new objects with the enumerable types, I got references and the IEnum modified error while browsing through it.

I changed it a little : it does'nt clone Lists anymore , but rather populate them with cloned objects.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections;

namespace YourNameSpace
{
///
/// BaseObject class is an abstract class for you to derive from.

/// Every class that will be dirived from this class will support the

/// Clone method automaticly.

/// The class implements the interface ICloneable and there

/// for every object that will be derived

/// from this object will support the ICloneable interface as well.

///


public abstract class ObjetClonable : ICloneable
{
///
/// Clone the object, and returning a reference to a cloned object.

///

/// Reference to the new cloned

/// object.

public object Clone()
{
//First we create an instance of this specific type.

object newObject = Activator.CreateInstance(this.GetType());

//We get the array of properties for the new type instance.

//FieldInfo[] properties = newObject.GetType().GetFields();

PropertyInfo[] properties = newObject.GetType().GetProperties();

int i = 0;

foreach (PropertyInfo prop in this.GetType().GetProperties())
{
//We query if the properties support the ICloneable interface.

Type ICloneType = prop.PropertyType.
GetInterface("ICloneable", true);

//We check if the object support the IEnumerable interface, so if it does we need to enumerate all its items and check if they support the ICloneable interface.

Type IEnumType = prop.PropertyType.GetInterface("IList", true);

if (ICloneType != null && (prop.PropertyType != typeof(System.String)))
{
//Getting the ICloneable interface from the object.
//We use the clone method to set the new value to the field.

if (properties[i].CanWrite)
{
ICloneable IClone = (ICloneable)prop.GetValue(this, null);
properties[i].SetValue(newObject, IClone.Clone(), null);
}
}
else
{
// If the field doesn't support the ICloneable interface then just set it If it is'nt Enumerable, if it is : we ll only later add objects to it !

if (properties[i].CanWrite && (IEnumType == null))
{
properties[i].SetValue(newObject, prop.GetValue(this,null),null);
}
}

if (IEnumType != null) // That properterty isn't cloned : it is created and populated with cloned objects.
{
//Get the IEnumerable interface from the field.

IEnumerable IEnum = (IEnumerable)prop.GetValue(this,null);

//This version support the IList

Type IListType = properties[i].PropertyType.GetInterface
("IList", true);

if (IListType != null)
{
//Getting the IList interface.

IList list = (IList)properties[i].GetValue(newObject,null);

int j = 0;
foreach (object obj in IEnum)
{

//Checking to see if the current item

//support the ICloneable interface.

ICloneType = obj.GetType().
GetInterface("ICloneable", true);

if (ICloneType != null)
{
//If it does support the ICloneable interface, we use it to set the clone of the object in the list.

ICloneable clone = (ICloneable)obj;

list.Add(clone.Clone());
}

j++;
}
}
}
i++;
}
return newObject;
}
}

}
QuestionAbout the System.Collections.DictionaryEntry in IDictionary
robrober
23:20 24 Dec '08  
Hi all,
I have a problem for clone the Dictionary<t,> object. Can U help me how to modify the code.Confused

The follow code is getting the IDictionary interface.
//Getting the dictionary interface.
IDictionary dic = (IDictionary)fields[i].GetValue(newObject);
j = 0;

foreach( DictionaryEntry de in IEnum ) // IEnum to DictionaryEntry is error {
//Checking to see if the item
//support the ICloneable interface.
ICloneType = de.Value.GetType().GetInterface( "ICloneable" , true );

if( ICloneType != null )<a href=""></a> {
ICloneable clone = (ICloneable)de.Value;

dic[de.Key] = clone.Clone();
}
j++;
}

My Clone class
    public class DictionaryClass : BaseObject
{
public Dictionary<int, System.Random> Dic = new Dictionary<int, System.Random>();
}

When clone the DictionaryClass to the other DictionaryClass, In code "foreach( DictionaryEntry de in IEnum )" will throw InvalidCastException

Error message: Specified cast is not valid.
AnswerRe: About the System.Collections.DictionaryEntry in IDictionary
robrober
18:29 27 Dec '08  
I find the answer.

else if (IDicType != null)
{
//Save the new clone item.
Dictionary<object, object> newDicCloneObjects = new Dictionary<object, object>();
//Getting the dictionary interface.
IDictionary dic = (IDictionary)field.GetValue(aNewObject);
IDictionary dicSource = (IDictionary)field.GetValue(aOldObject);
foreach (object key in dicSource.Keys)
{
if (dicSource[key] != null)
{
//Checking to see if the item support the ICloneable interface.
ICloneType = dicSource[key].GetType().GetInterface(C_ICloneable, true);
if (ICloneType != null)
{
ICloneable clone = (ICloneable)dicSource[key];
newDicCloneObjects.Add(key, clone.Clone());
}
else {
newDicCloneObjects.Add(key, CloneObject(dicSource[key]));
}
}
else {
newDicCloneObjects.Add(key, null);
}
}

foreach (object key in newDicCloneObjects.Keys)
{
if (dic.Contains(key) == true)
{
dic[key] = newDicCloneObjects[key];
}
else {
// Dictionary<TKay,TValue> doesn't support the ICloneable interface then just create instance.
// So the original items is losed and insert the item when throw the exception.
dic.Add(key, newDicCloneObjects[key]);
}
}
}


GeneralGetting InvalidOperationException
Jay Purkayastha
16:31 29 Sep '08  
I keep getting Exception saying, "Collection was modified; enumeration operation may not execute". I have references as IList types in 'thisObject' and need to clone them. Any help would be appreciated.

Thanks.

The code that I'm running:


Type IEnumerableType = fi.FieldType.GetInterface("IEnumerable", true);
if (IEnumerableType != null)
{
//Get the IEnumerable interface from the field.
IEnumerable IEnum = (IEnumerable)fi.GetValue(thisObj);

//This version support the IList and the IDictionary interfaces to iterate
//on collections.
Type IListType = fields[i].FieldType.GetInterface("IList", true);
Type IDicType = fields[i].FieldType.GetInterface("IDictionary", true);

int j = 0;
if (IListType != null)
{
//Getting the IList interface.
IList list = (IList)fields[i].GetValue(newObject);

foreach (object obj in IEnum)
{
//Checking to see if the current item support the ICloneable interface.
ICloneType = obj.GetType().GetInterface("ICloneable", true);

if (ICloneType != null)
{
//If it does support the ICloneable interface, we use it to set the clone of
//the object in the list.
ICloneable clone = (ICloneable)obj;

list[j] = clone.Clone();
}

//NOTE: If the item in the list is not support the ICloneable interface then
// in the cloned list this item will be the same item as in the original list
//(as long as this type is a reference type).
j++;
}
}
GeneralRe: Getting InvalidOperationException
jean.mourmon
0:49 25 Mar '09  
Hello

Did you get an answer fot that? I seem to get the same problem.

Best regards,

JM.
GeneralRun-time Speed [modified]
Jeremy F
8:15 15 Jul '08  
it looks like this code traverses through my arrays, ~1 million indicies, has anyone else noticed this or found a solution

re: So I just took off this whole part
if( IEnumerableType != null ) {
up to i++, and it seems to work fine, that was looping through any array

modified on Wednesday, July 16, 2008 4:50 PM

GeneralGetFields() is returning empty set?
YogSagot
8:43 12 Jun '08  
Hi there! I've got a problem with this code i cannot understand. In the very beginning there is following code

FieldInfo[] fields = newObject.GetType().GetFields();
And the problem is that it is returning empty set. and none of the fields are being copied.

What might be the reason?
AnswerRe: GetFields() is returning empty set?
Arthg
8:13 3 Jul '08  
http://msdn.microsoft.com/en-us/library/ch9714z3.aspx[^]

"Returns all the public fields of the current Type."

Could be your fields are all protected and/or private?
GeneralRe: GetFields() is returning empty set? [modified]
Jeremy F
6:28 15 Jul '08  
private/protected described on pg 2 of forum

modified on Tuesday, July 15, 2008 11:59 AM

GeneralDunno, but didn't worked for me
Sameers (theAngrycodeR )
11:28 22 Nov '07  
I had to quickly clone my big data class, so I tried it but it didn't worked for me at all. So I quickly wrote the following code (VB)

Inside Clone function:

Dim newObject As Object = Activator.CreateInstance(Me.[GetType]())

Dim fields As PropertyInfo() = newObject.[GetType]().GetProperties
For Each p As PropertyInfo In fields
If p.CanWrite And p.CanRead Then
Dim thisProperty As PropertyInfo = Me.GetType().GetProperty(p.Name)
p.SetValue(newObject, thisProperty.GetValue(Me, Nothing), Nothing)
End If
Next

Return newObject


Maybe, it work for someone else too (worked for me atleast).

FREE MSN Auto Responder[^]

History Remember Vendors, NOT Developers

GeneralRe: Dunno, but didn't worked for me
Member 3975685
4:03 10 Dec '07  
Your implementation does only perform a shallow copy of the object, which is already provided in the Object class (method MemberWiseClone).
GeneralDon't forget BindingFlags and Generics [modified]
k^s
0:26 15 Nov '07  
First of all thankyou for your implementation of cloning objects, I tryied something similar but was not as complete as yours.

=== BINDING FLAGS ===
Second, when I was reading and developing my Clonse class one of the first things i've learned is the use of BindingFalgs, which allow you to accurate the search of fields.

With your aproach, not all the fields are retrieved when .GetType().GetFields() is called, becaus you aren't passing any BindingFlags parameter. This affects a lot to the clonation because, for example, private members are not cloned.

Here my contribution:

Replace this code:
//We get the array of fields for the new type instance.
FieldInfo[] fields = newObject.GetType().GetFields(bf);

int i = 0;
foreach (FieldInfo fi in ObjectToClone.GetType().GetFields(bf))
{
...
}

For this one:
BindingFlags bf = BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Static;

//We get the array of fields for the new type instance.
FieldInfo[] fields = newObject.GetType().GetFields(bf);

int i = 0;
foreach (FieldInfo fi in ObjectToClone.GetType().GetFields(bf))
{
...
}

You can find more info in this article: Reflector.

=== GENERICS ===

Apply generics to this aproach is very simple, but must change a little bit the philosophy of the class.

implementing ICloneable.Clone forces you to return object, while we want to use Generics. This implies that our Clone function must return the correct type.

So we can do something like:
public T Clone(T ObjectToClone){
... // The code you've posted in your article, changing 'this' for 'ObjectToClone'.
}
But this implies not being implementing ICloneable.

The result of all of this is that if you want to use generics for clonation you can't implement ICloneable interface.

The solution i've found is to develp an static class T with an static function T Clone(T ObjectToClone), and use it as a tool when we need to clone. The code resutls very smart:

CLONATOR:

public static Clonator < T >
{
public static T Clone(ref T ObjectToClone)
{
// The code you've posted in your article, changing
// 'this' for 'ObjectToClone' and
// object newObject = Activator.CreateInstance(ObjectToClone.GetType());
// for
// T newObject = (T) Activator.CreateInstance(ObjectToClone.GetType());
}
}

How yo use it:


MyClass a = new MyClass(..);
// modify this class as wanted..
MyClass b = Clonator< MyClass >.Clone(ref a);

Of course you are free to test it and tell me your xperience!






-- modified at 5:43 Thursday 15th November, 2007
GeneralWhat about generics?
Richard Lennox
10:56 16 Jul '07  
How would you modify this to accept generic lists?
GeneralRe: What about generics?
ChrJaeger
6:46 25 Apr '08  
I changed the Sourcecode to support Generic Lists.
Also I Kicked out the i++ iterations, as we didn't need them realy.

public object Clone()
{
//First we create an instance of this specific type.
object newObject = Activator.CreateInstance(this.GetType());

foreach (FieldInfo fi in this.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
//We query if the fiels support the ICloneable interface.
Type ICloneType = fi.FieldType.
GetInterface("ICloneable", true);

if (ICloneType != null)
{
//Getting the ICloneable interface from the object.
ICloneable IClone = (ICloneable)fi.GetValue(this);

//We use the clone method to set the new value to the field.
fi.SetValue(newObject, IClone.Clone());
}
else {
if(fi.FieldType.GetInterface("IEnumerable",true) != null)
{
//Create an Instance of the Collection Type (instead of using a reference)
fi.SetValue(newObject, Activator.CreateInstance(fi.FieldType));
}
else {
// If the field doesn't support the ICloneable
// interface then just set it.
fi.SetValue(newObject, fi.GetValue(this));
}
}

//Now we check if the object support the
//IEnumerable interface, so if it does
//we need to enumerate all its items and check if
//they support the ICloneable interface.
Type IEnumerableType = fi.FieldType.GetInterface
("IEnumerable", true);
if (IEnumerableType != null)
{
//Get the IEnumerable interface from the field.
IEnumerable IEnum = (IEnumerable)fi.GetValue(this);

//This version support the IList and the
//IDictionary interfaces to iterate on collections.
Type IListType = fi.FieldType.GetInterface
("IList", true);
Type IDicType = fi.FieldType.GetInterface
("IDictionary", true);

if (IListType != null)
{
//Getting the IList interface.
IList list = (IList)fi.GetValue(newObject);

foreach (object obj in IEnum)
{
//Checking to see if the current item
//support the ICloneable interface.
ICloneType = obj.GetType().
GetInterface("ICloneable", true);

if (ICloneType != null)
{
//If it does support the ICloneable interface,
//we use it to set the clone of
//the object in the list.
ICloneable clone = (ICloneable)obj;
list.Add(clone.Clone());
// list[j] = clone.Clone();
}

//NOTE: If the item in the list is not
//support the ICloneable interface then in the
//cloned list this item will be the same
//item as in the original list
//(as long as this type is a reference type).
}
}
else if (IDicType != null)
{
//Getting the dictionary interface.
IDictionary dic = (IDictionary)fi.
GetValue(newObject);

foreach (DictionaryEntry de in IEnum)
{
//Checking to see if the item
//support the ICloneable interface.
ICloneType = de.Value.GetType().
GetInterface("ICloneable", true);

if (ICloneType != null)
{
ICloneable clone = (ICloneable)de.Value;
dic.Add(de.Key, clone.Clone());
//dic[de.Key] = clone.Clone();
}
}
}
}
}
return newObject;
}

It just works fine for me.
QuestionRe: What about generics? [modified]
liaokobe
21:17 24 Nov '08  
Generic List works fine, and how to support Generic Dictionary?
The code "foreach (DictionaryEntry de in IEnum)" will throw an InvalidCastException.

So I changed the code to clone Generic Dictionary as follow:
else if (IDicType != null)
{
//Getting the dictionary interface.
IDictionary dic = (IDictionary)fi.GetValue(newObject);
IDictionary dicSource = (IDictionary)fi.GetValue(this);
foreach (object key in dicSource.Keys)
{
//Checking to see if the item support the ICloneable interface.
ICloneType = dicSource[key].GetType().GetInterface("ICloneable", true);
if (ICloneType != null)
{
ICloneable clone = (ICloneable)dicSource[key];
dic.Add(key, clone.Clone());
}
else dic.Add(key, dicSource[key]);
}
}

Roll eyes

modified on Tuesday, November 25, 2008 2:49 AM

AnswerRe: What about generics?
sumitkm
21:01 25 Jan '09  
Thanks a million to the original author as well as the above modification for generics. Saved me a night's work. I have a very similar technique for cloning my entities. However recently I introduced generic collections in some of my entities down the the hierarchy. This code helped me clone them as well.

One difference I have is instead of fields I clone properties.

Thanks a ton once again.Thumbs Up
-Sumit.
QuestionHow about event handlers? [modified]
Mohammad Hamed
7:45 12 Aug '06  
Hello

If I have a class like the following, how can I use your approach to assign the event handlers to the new cloned object?

public class MyTextBox : TextBox, ICloneable
{
public object Clone()
{
MyTextBox clone = new MyTextBox();
clone.Click += this.Click; //compiler error!
The event '....Click' can only appear on the left hand side of += or -=
}
}



Mohammed Hamid A.

GeneralCopy of base class members [modified]
Nicolas Bonamy
6:32 25 Jul '06  
Hello,

I had to reuse this implementation on my own classes with different specifications:
- we only wanted to copy primitive types plus some "basic" .NET types (string, enum, DateTime...)
- we needed to copy all the inherited members
- we only wanted to copy non public fields

I also noticed that GetFields does not necessary return the fields in the same order. I noticed it systematically on the first and second calls but for safety reasons I preferred to lookup the corresponding field every time.

I though I'd post my modified version... Sorry for the comments in french but that is a prerequisite of the project I am working on!

public virtual object Clone()
{
// on cree une nouvelle instance
Objet clone = (Objet) Activator.CreateInstance(this.GetType());

// le binding type qu'on utilise
BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic;

// on va remonter la hiérarchie des types
Type oldType = this.GetType();
Type newType = clone.GetType();
while (oldType != null && newType != null)
{
// les champs pour des deux instances
// on ne recupere pas necessairement les champs dans le meme ordre!
FieldInfo[] oldFields = oldType.GetFields(bf);
FieldInfo[] newFields = newType.GetFields(bf);

// on copie les types cloneable
foreach (FieldInfo oldFI in oldFields)
{
// recuperer le champ correspondant
FieldInfo newFI = null;
for (int i=0; i {
if (newFields[i].Name == oldFI.Name)
{
newFI = newFields[i];
break;
}
}
if (newFI == null)
{
continue;
}

// on recupere la valeur
object value = oldFI.GetValue(this);
if (value != null)
{
if ( oldFI.FieldType.IsPrimitive
|| oldFI.FieldType.IsEnum
|| oldFI.FieldType == typeof(String)
|| oldFI.FieldType == typeof(Decimal)
|| oldFI.FieldType == typeof(DateTime)
|| oldFI.FieldType == typeof(TimeSpan))
{
// on met a jour la valeur directement
newFI.SetValue(clone, value);
}
}
}

// iteration
oldType = oldType.BaseType;
newType = newType.BaseType;
}

return clone;
}

Voilà!



-- modified at 11:38 Tuesday 25th July, 2006
GeneralAnd better still....
duckman (the)
17:18 21 Mar '06  
Theres a lot of problems in this implementation but the idea has bee kicking around many places..

Before cloning anything in C# read this... It's an excelent article.
http://www.agiledeveloper.com/articles/cloning072002.htm

basicly it shows an excelent way to clone.

class myclass() : ICloneable
{
public readonly int v;
protected myclass(myclass another)
{
v = another.v;
}

public object Clone()
{
return new myclass(this);
}
}

This is elegant and customisable. If you can't see why then read the article...

Re the serilization "better way"; serialisation may not always be appropriate:
-it does not handle all feild types.
-not all feilds may be serizable
-cpu cost is very high compared to a copy constructor.
-public events and delegates tend to get messy.
-behavious of serialisation changed from .NET 1.1 to 2.0....



{

GeneralRe: And better still....
dotnetprgrmmr
11:40 17 Jul '06  
Sleek - but you have to modify the copy constructor if you add a new field to a class - with the solution in this article you don't
GeneralCritial Crash
Arash Sabet
5:42 8 Feb '06  
Please consider the following code segment in your article:
foreach( object obj in IEnum )
{
//Checking to see if the current item
//support the ICloneable interface.
ICloneType = obj.GetType().
GetInterface( "ICloneable" , true );

if( ICloneType != null )
{
//If it does support the ICloneable interface,
//we use it to set the clone of
//the object in the list.
ICloneable clone = (ICloneable)obj;

list[j] = clone.Clone();
}

//NOTE: If the item in the list is not
//support the ICloneable interface then in the
//cloned list this item will be the same
//item as in the original list
//(as long as this type is a reference type).

j++;
}

The foreach loop crashes immediately due to this expression: list[j] = clone.Clone(); because you're trying to modify the list contents but an enumerator remains valid as long as the collection remains unchanged. If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and its behavior is undefined.
Any solutions?

Arash Sabet
Computer Engineer
E-mail: arash.afifi@gmail.com
GeneralRe: Critial Crash
Arash Sabet
7:33 8 Feb '06  
Again:
If we equip the folliwing if statetment inside the foreach loop you will figure out that list[j] is pointing to the same 'obj' object. That's why an exception is thrown during iteration iEnum object:

if( FieldInfo.ReferenceEquals(list[j],obj) )
{
....
}

The above if statemtent returns true, so the body of foreach loop has to be optimized and modified.

Arash Sabet
Computer Engineer
E-mail: arash.afifi@gmail.com
QuestionRe: Critial Crash
Bernd Kicker
5:03 29 May '07  
Hi,

How could this be implemented. I have a generic List property (List).

regards



Bernd
GeneralRe: Critial Crash
Arash Sabet
11:33 8 Feb '06  
Still I believe that this cloning routine is not mature enough to use it in serious applications because:

1. It doesn't clone referenced values. Just sets references! this is not the meaning of deep copying.
2. It doesn't support objects inherited from super classes. The fields of super classes (base classes) can't be iterated in the way that this article describes.

Again this is not a mature article. Just throwing some idea.

Arash Sabet
Computer Engineer
E-mail: arash.afifi@gmail.com


Last Updated 30 Dec 2002 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010