Memorizza un riferimento di una classe interna in una variabile che verrà solo utilizzata localmente (ad esempio all'interno di una funzione) sprecata di memoria?

3

Ad esempio

class A 
{
    public int data1 {get; set;}
    public int data2 {get; set;}
}
class B 
{
    public A objectA;
}
class C
{
    public B objectB;
}
class D
{
    public C objectC
}
class E
{
    public D objectD;
}

class Caller
{
    public void foo(E input)
    {
        var bar = input.objectD.objectC.objectB.objectA;

        // code that looks nice
        if (bar.data1 == 1)
        {
            // do something
        }

        // code that looks nice again
        if (bar.data2 == 2)
        {
            // do something again
        }

        // but why?
        if (input.objectD.objectC.objectB.objectA.data1 == 0)
        {
        }
    }
}

Proprio per il mio scopo, ecco un esempio di chiamata per una proprietà che è annidata in profondità all'interno di una classe interna. Sicuramente una classe che richiede una chiamata così profonda per accedere ai dati richiede il refactoring. Ma come esempio di ciò che sto cercando di dire, considera la classe E che ha una proprietà di classe D che fa riferimento ad altre classi fino alla classe A che contiene i dati di cui abbiamo bisogno.

Per evitare di digitare una chiamata a lungo termine su objectA proveniente dalla classe E, memorizzo objectA in una variabile. Se l'oggetto deve essere usato solo nell'ambito di poche righe, sarebbe uno spreco di memoria? Oltre a renderlo più facile da digitare, leggibile o forse anche mantenibile; quali altri meriti ci sono?

    
posta reverb 31.01.2018 - 01:52
fonte

3 risposte

11

Puoi usare le variabili locali quanto vuoi. Sono super economici (praticamente totalmente gratuiti) e offrono l'opportunità di documentare (scegliendo un nome significativo) quello che stai facendo.

Personalmente, mi piacciono le variabili locali, perché trovo che aumentano la leggibilità e tendono a facilitare il debugging: puoi vedere rapidamente i loro valori durante un singolo stepping, e quando si verificano eccezioni, le espressioni più brevi che impostano le variabili locali aiutano a restringerle.

Tuttavia, alcuni trovano estremamente fastidioso e preferiscono ripetere le espressioni piuttosto che raccogliere informazioni in variabili locali. Potrebbero dire, perché stai catturando questo valore in una variabile locale? Ti aspetti che cambi (e vuoi lavorare solo con il valore originale) ??

Talvolta a questi argomenti c'è il merito, ma io tendo a non essere d'accordo con loro. Quando vedo usi ripetuti di espressioni complesse, pongo la stessa domanda da un altro orientamento: perché il programmatore continua a ripetere la stessa espressione - si aspettano che cambi (e vuole lavorare ogni volta con il nuovo valore) ??

Molti algoritmi non funzioneranno se determinati valori cambiano entro poche righe di codice; anche se fortunatamente, si scopre che in genere non lo fanno, quindi non è un problema così grande come potremmo capire, e forse è più una questione di stile, penso, come usare le variabili locali e ripetersi .

(Si prega di notare che quanto sopra sostiene l'uso di variabili locali come temporanee, ma non di campi aggiuntivi come provvisori.)

    
risposta data 31.01.2018 - 03:14
fonte
1

Sì ... No ... Forse. In generale, non saprai se si tratta di memoria sprecata.

Se ti importa? No. Il compilatore si occupa di questo. Lascia che il compilatore faccia il suo lavoro.

Quello che ti interessa è la leggibilità E il codice che continua a fare lo stesso.

L'utilizzo di vars in questo modo può aumentare la leggibilità eliminando lunghe code di codice.

Tuttavia, il codice deve continuare a fare lo stesso, ci sono almeno 2 cose che richiedono attenzione: Devi essere assolutamente sicuro che stai memorizzando un riferimento e non una copia nella tua variabile, questa è una fonte di molti bug. Inoltre è necessario assicurarsi che la lettura di a.b.c.d.e.f non abbia effetti collaterali da qualche parte lungo la catena. Le proprietà possono avere effetti collaterali solo leggendole.

    
risposta data 31.01.2018 - 09:20
fonte
0

If the object is only to be used within the scope of a few lines would it be a waste of memory?

È difficile rispondere con precisione, ma io vado con "no" (non sono il tipo di persona su cui contare per precisione tecnica). Penso che sia meglio considerarlo semplicemente "no". Potrebbe esserci qualche caso davvero oscuro in cui ciò non è vero, ma lo vedo come meglio scoperto in una sessione di profiling quando analizzo lo smontaggio risultante, e anche allora direi ancora che la risposta è "no" e solo passare come una stranezza. :-D

Perché abbiamo già una quantità fissa di memoria veramente veloce messa da parte nei registri. I compilatori generalmente allocano queste variabili locali in registri. E la variabile non richiede necessariamente "memoria di registro in più" perché il risultato dell'espressione memorizzata dovrebbe essere generalmente spostato in un registro prima di poter eseguire qualsiasi istruzione su di esso.

E a volte i risultati vengono riversati nello stack, ma lo stack è la memoria preallocato che viene spuntata quando la variabile analogica esce dallo scope (o quando l'espressione non è più usata), e lo stesso si applica ai risultati dell'espressione che la variabile memorizza. Quindi, rispetto all'espressione stessa, il modo pratico di pensarlo dal punto di vista della memoria è che è assolutamente gratuito.

Aside from making it easier to type, readable, or maybe even maintainable; what other merits are there?

Se il compilatore non è così intelligente, catturare i risultati di un'espressione in una variabile può aiutare a allocare i registri in modo più efficace ed evitare di ripetere le stesse istruzioni coinvolte per valutare l'espressione. Tuttavia, questo è un motivo generalmente orribile per usare più variabili per un'espressione di base, perché in primo luogo i compilatori sono in genere molto intelligenti, e in secondo luogo non è molto produttivo cercare di aiutare i compilatori ad eseguire l'allocazione dei registri e la selezione delle istruzioni. Vuoi andare con il flusso dell'ottimizzatore e lasciarti aiutare, non provare a sconfiggerlo e ad arrampicarti sulle dita dei piedi, altrimenti potresti anche scrivere codice in assembly.

Quindi penso che tu abbia già elencato la maggior parte dei meriti. Volevo entrare qui perché non è così raro incontrare persone che hanno paura di immagazzinare una variabile locale per paura di avere qualche tipo di impatto memoria / prestazioni, e che la paura potrebbe diventare molto controproducente. Quasi certamente non, e in qualche oscuro caso ipotetico, potrebbe effettivamente avere l'effetto opposto - ma ancora una volta non dovresti usare le variabili locali con l'intenzione di cercare di aiutare gli ottimizzatori in contrasto con le buone ragioni che hai elencato come leggibilità e manutenibilità. Lo sottolineo solo perché l'intuizione che le variabili locali costano qualcosa è potenzialmente sbagliata perché le stesse cose che si desidera memorizzare analogicamente alla variabile locale devono essere comunque spostate / caricate in un registro e sono suscettibili alle stesse fuoriuscite di stack. / p>

Personalmente mi piace quando le persone acquisiscono i risultati di un'espressione lunga su una variabile locale (o idealmente una costante denominata se non può cambiare da quel punto in poi), poiché non solo riduce la quantità di codice che devo leggere, ma anche comunicando che tutto ciò che fa riferimento da quel momento in poi accedendo alla stessa cosa a colpo d'occhio. E naturalmente legando all'esempio mantenibile, se l'ipotesi che tutto da quel punto in poi acceda allo stesso risultato, ti dà una riga di codice da cambiare se il risultato deve cambiare rispetto a molti.

    
risposta data 31.01.2018 - 19:28
fonte

Leggi altre domande sui tag