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()));
        });
    }
È stato utile?

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();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top