How to pass a value to a list and leave it static?

0

I have a list of objects that I'm filling it in as follows:

var props = type.GetRuntimeProperties();

var obj = new T();

for (int i = 0; i < readerCache.Count; i++)
{
    var prop = props.Single(x => x.GetColumnName().ToLower() == readerCache.ElementAt(i).Item1.ToLower());

    if (prop.GetCustomAttribute<Column>().Type == ColumnType.FK)
    {
        var method = typeof(SelectExtension).GetMethod("SelectSingle");

        var generic = method.MakeGenericMethod(prop.PropertyType);

        prop.SetValue(obj, generic.Invoke(null, new object[] { dBManager, $"WHERE id = '{readerCache.ElementAt(i).Item2}'" }));
    }
    else
    {
        prop.SetValue(obj, readerCache.ElementAt(i).Item2);
    }

    if ((i + 1) % props.Count() == 0)
    {
        objList.Add(obj);
    }
}

When I'm debugging, objects are being filled in correctly, but when the list finishes filling in, all elements are the same.

My suspicion is that you are passing the object by reference, not by value.

Why does this happen? How to fix?

    
asked by anonymous 11.01.2018 / 23:20

1 answer

0

A list of reference types is nothing more than a list of references. This means that each position in the list holds a reference to the inserted object.

  

Why does this happen?

var obj = new T();

for (int i = 0; i < readerCache.Count; i++)
{
    // Operações que possivelmente mudam a estrutura de 'obj' a cada iteração
    ...
    // Adição da referência de 'obj'
    objList.Add(obj);
}

As much as the structure of the object obj changes within the loop, the reference remains the same. Executing objList.Add(obj) you are always adding the reference of the initial object to the list, resulting in a list with several references of the same object (that is, all elements are equal).

  

How to fix?

  • Declare obj within the loop. This ensures that each object has a different address in memory and consequently distinct references will be added to the list of objects.
  • If the first option is not possible, I suggest you add a clone to your object list.
  • Creating a clone of an object in C # can be problematic. One of the simplest solutions is by serialization and deserialization. Using the framework Newtonsoft Json.NET , you can do something like this:

    objList.Add(JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(obj)));
    

    If you want, you can implement a custom extension method

    public static T Clone<T>(this T source)
    {
       return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source));
    }
    

    and then use it

    objList.Add(obj.Clone());
    
        
    12.01.2018 / 13:44