Domanda

Sto lavorando su un codice di simulazione in C #, e ho qualche codice lungo le linee di:

public void predict(Point start, Point end)
{
    end.velocity = start.velocity + dt * end.acceleration;
    end.position = start.position + dt * end.velocity;
}

Dove posizione, velocità, accelerazione sono alcuni tipi di dati vettoriali ho definito con operatori associati.

Così come codice in cui sto facendo:

StartPoint = EndPoint;
EndPoint = CurrentPoint;

Con Punto * essendo istanze di punti che sono diversi (Vector) tipi di dati primitivi (doppie) e non primitive.

Io corro in (ovvio) problema che il codice di cui sopra, molto probabilmente sarà semplicemente impostare StartPoint per puntare ai dati precedentemente EndPoint, e endpoint puntare a CurrentPoint.

Significato, se modifico nuovo CurrentPoint finirò EndPoint accidentalmente modifica.

In C ++ è semplice per evitare che dal momento che posso definire il mio operatore di assegnazione di fare una copia completa dei dati sottostanti all'interno degli oggetti il ??mio punto. Come posso evitare questo in C #?

Grazie per qualsiasi aiuto!

Modifica: La classe Vector è definito come

[Serializable]
public class Vector
{
    private Double[] data = new Double[Constants.Dimensions];

    ... snip ...

    public static Vector operator +(Vector lhs, Vector rhs)
    {
        Vector result = new Vector();
        for (UInt32 i = 0; i < Constants.dimensions; i++)
            result[i] = lhs[i] + rhs[i];
        return result;
    }

    lots more code here 
}
È stato utile?

Soluzione

Questo è uno dei problemi più brutte con l'IMHO C # design.

Se 'Point' è una struct (valore), quindi una copia membro a membro sarà effettuato, in modo da x = y farà un indipendente copia di y. Ma se è una classe (riferimento), x = y semplicemente puntare il riferimento x alla stessa memoria usato per y, così i due diventeranno semplicemente diversi 'alias' per gli stessi dati.

Le due soluzioni che conosco per il vostro problema sono i seguenti:

  • Usa uno struct. Questo vi darà il comportamento del valore-tipo che ci si aspetta per le classi di matematica. Per mantenere il vostro codice efficiente si può quindi bisogno di passare con riferimento in tutto il mondo al fine di evitare le struct copiati continuamente.

  • L'uso di una classe, ma essere molto molto attenti quando si usano = per assicurarsi di conservare una copia indipendente dei dati. Avrai bisogno di cambiare x = y a qualcos'altro, per esempio x = new Point(y);.

Altri suggerimenti

Potreste usare Clone (), e quindi implementare il deep-copia come ne avete bisogno?

StartPoint = EndPoint; 
EndPoint = (Point)CurrentPoint.Clone(); 

Si vuole passare per riferimento. I suoi metodi sono attualmente passaggio per valore, cioè il valore delle variabili vengono copiati. Il metodo sarà sempre lavorando con una copia dei dati.

Per passare con riferimento effettuare le seguenti operazioni:

public void predict(ref Point start, ref Point end)
{
    end.velocity = start.velocity + dt * end.acceleration;
    end.position = start.position + dt * end.velocity;
}

Si dovrà quindi chiamare il metodo con la parola chiave ref in questo modo:

predict(ref start, ref end);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top