Back to Blog
C#

c# memberwiseclone: Shallow Copy Basics

c# memberwiseclone: Learn how MemberwiseClone creates shallow copies in C#, its limitations, and when to use it for object cloning in .NET applications.

MemberwiseCloneObject CloningShallow CopyICloneableC# Programming.NET
Diagram illustrating shallow copy vs deep copy in C# with MemberwiseClone

c# memberwiseclone requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

The MemberwiseClone method in C# is a protected method on System.Object that creates a shallow copy of the current object. It is the simplest way to clone an object without writing manual field-by-field copying. However, its behavior is often misunderstood, especially regarding reference types and nested objects.

How MemberwiseClone Works

MemberwiseClone is a native method that allocates a new object of the same type and copies all non-static fields from the original object to the new one. For value-type fields, the values are copied directly. For reference-type fields, only the reference is copied, meaning the new object points to the same instance as the original.

Because the method is protected, you cannot call it directly from outside the class. Instead, you typically expose it through a public method or by implementing the ICloneable interface.

public class Person { public string Name { get; set; } public Address HomeAddress { get; set; } public Person ShallowCopy() => (Person)MemberwiseClone(); } public class Address { public string Street { get; set; } public string City { get; set; } }

In the example above, calling ShallowCopy() on a Person instance creates a new Person whose Name string and HomeAddress reference are the same as the original. The HomeAddress object itself is not duplicated.

Shallow Copy vs Deep Copy

A shallow copy duplicates the top-level object but shares references to any reference-type fields. A deep copy duplicates the entire object graph, including all nested objects. The distinction is critical when the object contains mutable reference types.

Consider this scenario:

var original = new Person { Name = "Alice", HomeAddress = new Address { Street = "123 Main St", City = "Springfield" } }; var shallow = original.ShallowCopy(); shallow.HomeAddress.City = "Shelbyville"; Console.WriteLine(original.HomeAddress.City); // Output: Shelbyville

Because HomeAddress is shared, modifying the copy's address also affects the original. A deep copy would create a new Address instance, isolating the two objects.

Implementing ICloneable with MemberwiseClone

The ICloneable interface requires a Clone() method that returns an object. Many developers use MemberwiseClone as a quick implementation, but this can be misleading if the class contains reference types. The interface does not specify whether the clone should be shallow or deep, so you must document the behavior.

public class Person : ICloneable { public string Name { get; set; } public Address HomeAddress { get; set; } public object Clone() => MemberwiseClone(); }

This implementation provides a shallow copy. If you need a deep copy, you must manually clone reference-type fields:

public object Clone() { var clone = (Person)MemberwiseClone(); clone.HomeAddress = new Address { Street = HomeAddress.Street, City = HomeAddress.City }; return clone; }

Be aware that MemberwiseClone does not call any constructors, so any initialization logic in the constructor is skipped. This can be an advantage for performance but a pitfall if the object relies on constructor behavior.

When to Use MemberwiseClone

Use MemberwiseClone when you need a fast, simple shallow copy and you understand that reference types are shared. Common use cases include:

  • Implementing value-object-like classes where fields are immutable or where sharing references is acceptable.
  • Creating a prototype pattern where the copy is intended to be a starting point and you manually handle nested objects.
  • Copying objects that contain only value types or immutable strings, making shallow and deep copies effectively identical.

Avoid MemberwiseClone when the object graph contains mutable reference types and you need isolation. In such cases, a deep copy is necessary, and MemberwiseClone alone is insufficient.

Performance and Memory Considerations

MemberwiseClone is implemented natively in the CLR and is generally faster than a manual field-by-field copy because it copies all fields in a single operation. It does not invoke constructors or virtual methods, reducing overhead. However, the exact performance gain depends on the object size and the cost of the alternative implementation.

Memory usage is another factor. A shallow copy allocates memory for the new top-level object but does not allocate additional memory for referenced objects. This can be memory-efficient when sharing is acceptable, but it also means changes to nested objects propagate across all copies.

If you need deep copies, the cost increases because you must recursively clone every reference type. In that case, consider serialization-based approaches or manual cloning, depending on the complexity of the object graph.

Common Pitfalls and Limitations

One common mistake is assuming MemberwiseClone creates a deep copy. It does not, and this misunderstanding leads to subtle bugs when nested objects are modified. Another pitfall is exposing MemberwiseClone without documenting its shallow behavior, especially when implementing ICloneable.

The method is protected, so it cannot be called on an instance from outside the class hierarchy. This forces you to wrap it in a public method, which is good practice but adds a small layer of indirection.

MemberwiseClone also copies fields regardless of their accessibility. Private fields are copied as well, which is usually desirable. However, if a field is marked readonly, the copy will still have the same value, but the readonly constraint is not enforced on the new object because no constructor runs. This can lead to unexpected mutability if you later modify the field through a method that assigns to it.

Finally, MemberwiseClone is not virtual. You cannot override it to customize the cloning behavior in derived classes. If a derived class adds reference-type fields, a base class implementation of MemberwiseClone will still copy those fields, but you must ensure the derived class exposes its own cloning method if needed. The method always copies all fields of the runtime type, so it works correctly even when called from a base class reference, but you lose the ability to inject custom logic.

Understanding these limitations helps you decide when MemberwiseClone is appropriate and when a more explicit cloning strategy is required.

c# memberwiseclone: Shallow Copying Explained | RYUSLOG DEV