clonazione di un oggetto in C #
-
29-09-2019 - |
Domanda
Voglio clonare un oggetto con utilizzando l'interfaccia ICloneable
e per qualche motivo non riesco a clonare nel mio programma. Ecco il mio codice:
public class GeoInfo : ICloneable
{
private long InfoID;
private string InfoName;
private Location InfoLocation;
private string Description;
private InfoTypes InfoType;
public GeoInfo(long InfoID)
{
this.InfoID = InfoID;
}
public GeoInfo(long InfoID, Location InfoLocation):this(InfoID)
{
this.InfoLocation = InfoLocation;
}
public GeoInfo(long InfoID, string InfoName, Location InfoLocation, string Description, InfoTypes InfoType):this(InfoID,InfoLocation)
{
this.InfoName = InfoName;
this.Description = Description;
this.InfoType = InfoType;
}
public object ICloneable.Clone()
{
GeoInfo toReturn = new GeoInfo(InfoID, InfoName, InfoLocation, Description, InfoType);
return (object)toReturn;
}
}
all'interno di un'altra classe quando sto cercando di utilizzare il metodo Clone()
, per qualche motivo il compilatore non riesce a trovare il metodo. Ecco il mio altro metodo che sta cercando di Clone: ??
public InfoLayer(string LayerName,List<GeoInfo> oldGeoInfos)
{
this.LayerName = LayerName;
this.GeoInfos = new List<GeoInfo>();
oldGeoInfos.ForEach((item) =>
{
GeoInfos.Add((GeoInfo)((ICloneable)item.Clone()));
});
}
Soluzione
Le parentesi intorno alla vostra cast non sono corretti. Dovrebbe essere visualizzato
GeoInfos.Add((GeoInfo)((ICloneable)item).Clone());
(A proposito: perché il .ForEach ()
this.GeoInfos = oldGeoInfos.Select(item => ((GeoInfo)((ICloneable)item.Clone()))).ToList();
fa il lavoro pure.)
Altri suggerimenti
Come altri hanno detto è stato implementato l'interfaccia explicitly.What che faccio è creare un altro metodo che restituisce una versione typesafe del metodo clone così ho tendono ad includere.
public GeoInfo Clone()
{
return new GeoInfo(InfoID, InfoName, InfoLocation, Description, InfoType);
}
e cambiare il metodo clone esplicitamente implementato da (il modificatore pubblico deve essere rimosso) ...
object ICloneable.Clone()
{
return Clone(); //will call the public method as above
}
In questo modo non c'è bisogno di getto da un oggetto al tipo reale.
Per quanto ci sono un certo numero di difficoltà con ICloneable:
- Non so se il clone dovrebbe essere un profonda o superficiale clone
- È necessario fornire un meccanismo per le classi derivate di clonare se stessa, che si può tentare di fare tramite metodi virtuali. Io tendo a sigillare le mie lezioni in casi non posso garantire una corretta clonazione a tipi derivati, ma che è una decisione da prendere a base intorno al vostro architcture e le esigenze.
Si deve solo chiamare il metodo
public object Clone()
Modifica
Oppure chiamare il metodo
oldGeoInfos.ForEach((item) =>
{
GeoInfos.Add((GeoInfo)(((ICloneable)item).Clone()));
});
nota ()
supplementare.
La linea deve leggere
GeoInfos.Add((GeoInfo)((ICloneable)item).Clone());
Ma considerare nella tua classe GeoInfo
di non utilizzare implementazione dell'interfaccia esplicita (il tuo esempio non deve compilare in ogni caso), in modo che legge:
public object Clone()
{
//...
}
Poi si può semplicemente fare
GeoInfos.Add((GeoInfo)item.Clone());
è stato implementato ICloneable.Clone
esplicitamente, che richiede che l'oggetto è gettato a ICloneable
prima che la canna metodo di essere chiamato.
interfaccia esplicita Attuazione su MSDN.
Se si desidera che il metodo richiamabile sul vostro oggetto, modificare la dichiarazione metodo per:
public object Clone()
In alternativa, se si desidera mantenere il controllo di tipo statico, lascia l'implementazione corrente così com'è, e aggiungere il seguente:
public GeoInfo Clone()
{
return ((ICloneable)this).Clone();
}