3

I would like to confirm that the answer to https://stackoverflow.com/a/10387423/368896 is correct and applies in the following case:

// These IDataHolder instances contains a property "name",
// and another data member that is a large array.
// A copy constructor exists that makes a deep copy.
public MyFunction(IEnumerable<IDataHolder> columns)
{
    // Is the copy constructor called?
    this.columns = columns.ToDictionary(c => c.info.name, c => c);
}

I am fairly confident that the copy constructor is not called; i.e., that the call to toDictionaary does not perform a deep copy but only copies references.

However, I cannot find confirmation of this.

Am I correct? Does toDictionary() perform a shallow copy only?

(Note: I have a strong C++ background, but am new to C#.)

Community
  • 1
  • 1
Dan Nissenbaum
  • 13,558
  • 21
  • 105
  • 181
  • 1
    Yes, shallow copy only (EDIT: I mean, copies references. It will not do a shallow copy of `c` elements in this case, but essentially makes a shallow copy of the _dictionary_). If you want to do a deep copy, you can call the `ToDictionary` overload that lets you project the keys/values and manually call the copy constructor yourself. – Chris Sinclair Jun 25 '13 at 22:17
  • 1
    Shallow copy. FYI, with [LINQPad](http://www.linqpad.net/) you can test this kind of hypotheses out in < 30 seconds. It even comes in a portable version. – Jon Jun 25 '13 at 22:19

2 Answers2

3

It will only copy over the object references and not perform any cloning (shallow, or deep) at all.

Normally, it will perform shallow copies of structs though just out of virtue of the pass-by-value semantics for structs. However in this case, since you have it typed as an interface, I do believe the value types will be boxed and not shallow copied.

If you need to perform your own deep copy of the elements, then you can use this overload and call the copy constructor yourself:

public MyFunction(IEnumerable<IDataHolder> columns)
{
    //replace c.DeepCopy() with whatever the deep copying function is
    this.columns = columns.ToDictionary(c => c.info.name, c => c.DeepCopy());
}

The main reason for this is because C# does not have a native, built-in method for deep copying*. This is typically to be implemented per-object as the developer needs.

* there are some ways to perform generalized deep copying which you can employ if your design warrants it

Community
  • 1
  • 1
Chris Sinclair
  • 22,858
  • 3
  • 52
  • 93
2

No, the keys and values are both copied by value and this is a shallow copy.

Note, this is true regardless of the keys or values being value types or reference types.

For clarity, value types being copied by value means the fields are copied by value.

For additional clarity, for reference types, the references are copied by value. Since the references are copied by value, it's a shallow copy.

jason
  • 236,483
  • 35
  • 423
  • 525
  • Is this in contradiction to @ChrisSinclair's answer? He claims they are shallow copies; am I misunderstanding something in perceiving his answer and yours to be in contradiction? – Dan Nissenbaum Jun 25 '13 at 22:23
  • No, I mean the same thing. Shallow copy only. – jason Jun 25 '13 at 22:24
  • By *the values*, you mean the values are themselves the references to the underlying data, then? – Dan Nissenbaum Jun 25 '13 at 22:25
  • Correct. For a variable `x` of reference type, the *value* of `x` is a reference to an object. It is that value that is copied, *not* the referent object. – jason Jun 25 '13 at 22:26