Enumerable Cloner
EnumerableCloner<T> implements ICloner<IEnumerable<T>>.
// Create cloner
ICloner<IEnumerable<int>> cloner = new EnumerableCloner<int>().SetReadOnly();
// Create list
List<int> list = new List<int> { 1, 2, 3 };
// Create clone
IEnumerable<int> clone = cloner.Clone(list);
EnumerableCloner.Create(elementType, elementCloner) also creates same IEnumerable<T> cloner.
ICloner<IEnumerable<int>> cloner =
(ICloner<IEnumerable<int>>)
EnumerableCloner.Create(typeof(int)).SetReadOnly();
List Cloner
ListCloner<List, Element> implements ICloner<List> cloner.
// Create cloner
ICloner<List<int>> cloner = new ListCloner<List<int>, int>().SetReadOnly();
// Create list
List<int> list = new List<int> { 1, 2, 3 };
// Create clone
List<int> clone = cloner.Clone(list);
ListCloner.Create(listType) also creates list same cloner.
// Create cloner
ICloner<List<int>> cloner =
(ICloner<List<int>>)
ListCloner.Create(typeof(List<int>)).SetReadOnly();
ListCloner<Interface, Element, Implementation> implements ICloner<Interface> cloner.
// Create cloner
ICloner<IList<int>> cloner =
new ListCloner<IList<int>, int, List<int>>()
.SetReadOnly();
// Create list
IList<int> list = new List<int> { 1, 2, 3 };
// Create clone
IList<int> clone = cloner.Clone(list);
ListCloner.Create(interfaceType, implementationType) also creates list cloner.
// Create cloner
ICloner<IList<int>> cloner =
(ICloner<IList<int>>)
ListCloner.Create(typeof(IList<int>), typeof(List<int>))
.SetReadOnly();
Array Cloner
ArrayCloner<Element> implements ICloner<Element[]> cloner.
// Create cloner
ICloner<int[]> cloner = new ArrayCloner<int>().SetReadOnly();
// Create array
int[] list = new int[] { 1, 2, 3 };
// Create clone
int[] clone = cloner.Clone(list);
ArrayCloner.Create(element) also creates list cloner.
// Create cloner
ICloner<int[]> cloner =
(ICloner<int[]>)
ArrayCloner.Create(typeof(int)).SetReadOnly();
ThrowOnNull
.SetThrowOnNull(false) sets policy to pass null as is. This is default policy.
// Create cloner
ICloner<int[]> cloner =
(ICloner<int[]>)
ArrayCloner.Create(typeof(int))
.SetThrowOnNull(false)
.SetReadOnly();
// Create clone (of null)
int[]? clone = cloner.Clone(null!); // -> null
.SetThrowOnNull(true) sets policy to throw ArgumentNullException on null input value.
try
{
// Create cloner
ICloner<int[]> cloner =
(ICloner<int[]>)
ArrayCloner.Create(typeof(int))
.SetThrowOnNull(true)
.SetReadOnly();
// Create clone (of null)
int[]? clone = cloner.Clone(null!);
}
catch (ArgumentNullException)
{
}
Deep Cloner
.SetElementCloner(elementCloner) assigns a cloner that clones each element. If assigned the clone is deep, otherwise shallow.
// Create record cloner
ICloner<MyRecord> recordCloner = (ICloner<MyRecord>)RecordCloner.Create(typeof(MyRecord));
// Create array cloner
ICloner<MyRecord[]> cloner =
(ICloner<MyRecord[]>)
ArrayCloner.Create(typeof(MyRecord))
.SetElementCloner(recordCloner)
.SetReadOnly();
// Create record
MyRecord myRecord = new MyRecord { Id = 1 };
// Create array
MyRecord[] array = new[] { myRecord };
// Create array clone
MyRecord[] clones = cloner.Clone(array);
// Assert not same reference
WriteLine(Object.ReferenceEquals(clones, array)); // False
WriteLine(Object.ReferenceEquals(clones[0], array[0])); // False
public record MyRecord
{
public int Id;
}
Graph Cloner
Use .SetCyclical(true) to indicate cyclical graph clone.
// Create node cloner
ICloner<Node> nodeCloner = (ICloner<Node>)RecordCloner.Create(typeof(Node)).SetCyclical(true);
// Create array cloner
ICloner<Node[]> graphCloner =
(ICloner<Node[]>)
ArrayCloner.Create(typeof(Node))
.SetElementCloner(nodeCloner)
.SetCyclical(true)
.SetReadOnly();
// Create graph
Node node1 = new Node { Id = 1 };
Node node2 = new Node { Id = 2 };
Node node3 = new Node { Id = 3 };
node1.Edges.Add(node2);
node2.Edges.Add(node3);
node3.Edges.Add(node1);
Node[] graph = new[] { node1, node2, node3 };
// Clone
Node[] clone = graphCloner.Clone(graph);
// Assert not same reference
WriteLine(Object.ReferenceEquals(graph, clone)); // False
WriteLine(Object.ReferenceEquals(graph[0], clone[0])); // False
public class Node
{
public int Id;
public List<Node> Edges = new List<Node>();
}
⇒
Full Example
Full example
using System;
using System.Collections.Generic;
using System.Linq;
using Avalanche.Utilities;
using static System.Console;
public class enumerablecloner
{
public static void Run()
{
// Enumerable Cloner
{
// <01>
// Create cloner
ICloner<IEnumerable<int>> cloner = new EnumerableCloner<int>().SetReadOnly();
// Create list
List<int> list = new List<int> { 1, 2, 3 };
// Create clone
IEnumerable<int> clone = cloner.Clone(list);
// </01>
// Print clone
Print(clone);
}
{
// <02>
ICloner<IEnumerable<int>> cloner =
(ICloner<IEnumerable<int>>)
EnumerableCloner.Create(typeof(int)).SetReadOnly();
// </02>
// Create list
List<int> list = new List<int> { 1, 2, 3 };
// Create clone
IEnumerable<int> clone = cloner.Clone(list);
// Print clone
Print(clone);
}
// List Cloner
{
// <11>
// Create cloner
ICloner<List<int>> cloner = new ListCloner<List<int>, int>().SetReadOnly();
// Create list
List<int> list = new List<int> { 1, 2, 3 };
// Create clone
List<int> clone = cloner.Clone(list);
// </11>
// Print clone
Print(clone);
}
{
// <12>
// Create cloner
ICloner<List<int>> cloner =
(ICloner<List<int>>)
ListCloner.Create(typeof(List<int>)).SetReadOnly();
// </12>
// Create list
List<int> list = new List<int> { 1, 2, 3 };
// Create clone
List<int> clone = cloner.Clone(list);
// Print clone
Print(clone);
}
{
// <13>
// Create cloner
ICloner<IList<int>> cloner =
new ListCloner<IList<int>, int, List<int>>()
.SetReadOnly();
// Create list
IList<int> list = new List<int> { 1, 2, 3 };
// Create clone
IList<int> clone = cloner.Clone(list);
// </13>
// Print clone
Print(clone);
}
{
// <14>
// Create cloner
ICloner<IList<int>> cloner =
(ICloner<IList<int>>)
ListCloner.Create(typeof(IList<int>), typeof(List<int>))
.SetReadOnly();
// </14>
// Create list
IList<int> list = new List<int> { 1, 2, 3 };
// Create clone
IList<int> clone = cloner.Clone(list);
// Print clone
Print(clone);
}
// Array Cloner
{
// <21>
// Create cloner
ICloner<int[]> cloner = new ArrayCloner<int>().SetReadOnly();
// Create array
int[] list = new int[] { 1, 2, 3 };
// Create clone
int[] clone = cloner.Clone(list);
// </21>
// Print clone
Print(clone);
}
{
// <22>
// Create cloner
ICloner<int[]> cloner =
(ICloner<int[]>)
ArrayCloner.Create(typeof(int)).SetReadOnly();
// </22>
// Create array
int[] list = new int[] { 1, 2, 3 };
// Create clone
int[] clone = cloner.Clone(list);
// Print clone
Print(clone);
}
// ThrowOnNull
{
// <31>
// Create cloner
ICloner<int[]> cloner =
(ICloner<int[]>)
ArrayCloner.Create(typeof(int))
.SetThrowOnNull(false)
.SetReadOnly();
// Create clone (of null)
int[]? clone = cloner.Clone(null!); // -> null
// </31>
}
{
// <32>
try
{
// Create cloner
ICloner<int[]> cloner =
(ICloner<int[]>)
ArrayCloner.Create(typeof(int))
.SetThrowOnNull(true)
.SetReadOnly();
// Create clone (of null)
int[]? clone = cloner.Clone(null!);
}
catch (ArgumentNullException)
{
}
// </32>
}
// Deep Cloner
{
// <41>
// Create record cloner
ICloner<MyRecord> recordCloner = (ICloner<MyRecord>)RecordCloner.Create(typeof(MyRecord));
// Create array cloner
ICloner<MyRecord[]> cloner =
(ICloner<MyRecord[]>)
ArrayCloner.Create(typeof(MyRecord))
.SetElementCloner(recordCloner)
.SetReadOnly();
// Create record
MyRecord myRecord = new MyRecord { Id = 1 };
// Create array
MyRecord[] array = new[] { myRecord };
// Create array clone
MyRecord[] clones = cloner.Clone(array);
// Assert not same reference
WriteLine(Object.ReferenceEquals(clones, array)); // False
WriteLine(Object.ReferenceEquals(clones[0], array[0])); // False
// </41>
}
// Graph Cloner
{
// <51>
// Create node cloner
ICloner<Node> nodeCloner = (ICloner<Node>)RecordCloner.Create(typeof(Node)).SetCyclical(true);
// Create array cloner
ICloner<Node[]> graphCloner =
(ICloner<Node[]>)
ArrayCloner.Create(typeof(Node))
.SetElementCloner(nodeCloner)
.SetCyclical(true)
.SetReadOnly();
// Create graph
Node node1 = new Node { Id = 1 };
Node node2 = new Node { Id = 2 };
Node node3 = new Node { Id = 3 };
node1.Edges.Add(node2);
node2.Edges.Add(node3);
node3.Edges.Add(node1);
Node[] graph = new[] { node1, node2, node3 };
// Clone
Node[] clone = graphCloner.Clone(graph);
// Assert not same reference
WriteLine(Object.ReferenceEquals(graph, clone)); // False
WriteLine(Object.ReferenceEquals(graph[0], clone[0])); // False
// </51>
}
}
static void Print<T>(IEnumerable<T> enumr) => Console.WriteLine(String.Join(", ", enumr));
static void PrintArray<T>(IEnumerable<IEnumerable<T>> enumr) => Console.WriteLine($"[{String.Join("], [", enumr.Select(array => String.Join(", ", array)))}]");
// <98>
public record MyRecord
{
public int Id;
}
// </98>
// <99>
public class Node
{
public int Id;
public List<Node> Edges = new List<Node>();
}
// </99>
}