Come usare l’interfaccia ICloneable

1. Introduzione

Spesso vi è la necessità di eseguire una copia dell’istanza della classe con cui si sta lavorando, ovvero la creazione di una nuova istanza di una classe con lo steso valore di un’istanza esistente.

La procedura di copia non è un’operazione banale che non può essere fatta con un assegnamento, in quanto le classi sono tipi di riferimento e conseguentemente, per esempio, questa operazione

object a = new object {foo="bar"}
object b = a
b.foo = "new bar" //anche a.foo = "new bar"

porta alla modifica dell’attributo foo sia dell’oggetto a che dell’oggetto b.

2. Il metodo Object.MemberwiseClone()

Questo metodo è un metodo di Object e, conseguentemente, può assere applicato a tutti gli oggetti del nostro sistema.

In particolare il MemberwiseClone metodo crea una copia superficiale (shallow copy) creando un nuovo oggetto e quindi copiando i campi non static dell’oggetto corrente al nuovo oggetto.

Se un campo è di tipo:

  • Valore: viene eseguita una copia bit per bit del campo;
  • Riferimento: viene copiato solo il riferimento pertanto sia l’oggetto originale che il suo clone fanno riferimento allo stesso oggetto.

Questo metodo è il metodo base di tutti i metodi clone(), e viene utilizzato per la fase iniziale di shallow copy.

A questo metodo deve spesso seguire un’implementazione personalizzata al fine di ottenere la copia come desiderato (deep copy).

3. L’interfaccia ICloneable

Quando ho la necessità di implementare un metodo clone() che effettui una deep copy e che, conseguentemente, estenda il metodo MemberwiseClone di object posso implementare l’interfaccia ICloneable che contiene un solo metodo, Clone, il quale fornisce un supporto della clonazione aggiuntivo a quello di Object.MemberwiseClone.

L’interfaccia ICloneable richiede semplicemente che l’implementazione del valore restituito dal metodo Clone ritorni una copia dell’istanza dell’oggetto corrente.

Non specifica se l’operazione di duplicazione esegue una copia completa, una copia superficiale, o una via di mezzo, né richiede che tutti i valori della proprietà dell’istanza originale vengano copiati nella nuova istanza.

Tipicamente la struttura di una classe che implementa questa interfaccia è la seguente

public class ClassToClone : ICloneable
{
    public object Clone()
    {
        ClassToClone clone = (ClassToClone) this.MemberwiseClone();
        // logica di copia dei tipi di riferimento

        return clone;
    }
}

In ultima istanza specifico che il metodo clone ritorna un tipo object, come anche il metodo MemberwiseClone, conseguentemente la loro chiamata deve sempre essere preceduta da un cast del tipo di variabile che si sta clonando.

Indice

Share
Ultimi articoli
Join

Newsletter

Nessuno spam, solo articoli interessanti ;)

Focus

Post correlati

semaphoreslim

SmaphoreSlim 101

SemaphoreSlim è una classe che permette la sincronizzazione di n thread che hanno una risorsa (scarsa) condivisa limitandone l’uso ad un numero massimo.

interlocked

Interlocked 101

La sincronizzazione dei thread è un elemento fondamentale nella programmazione asincrona, ne ho infatti parlato in vari post. La soluzione più versatile è sicuramente utilizzare

event

Come testare gli eventi

Testare che degli eventi siano stato effettivamente lanciati in C# non è immediato. Tipicamente è possibile testare che un evento venga lanciato aspettando un ManualResetEvent

Codice Pragmatico

Contatti

Per informazioni, dubbi o consulenze non esitate a contattarmi.

Lascia un messaggio

Ricevi le ultime news

Iscrivi alla newsletter

Solo articoli interessanti, promesso ;)