2012-02-20 19 views
10

Sono curioso di sapere se tutti i cast di C# risultano nel pugilato, e se no, tutti i cast sono un'operazione costosa?Tutti i cast di C# danno luogo a boxe/unboxing

Esempio preso da Boxing and Unboxing (C# Programming Guide)

int i = 123; 
    // The following line boxes i. 
    object o = i; 

Questa riga causa ovviamente boxe (avvolgendo il tipo int come oggetto). Questa è un'operazione considerata costosa, dal momento che crea rifiuti che verranno raccolti.

E i cast di 2 tipi diversi di tipi di riferimento? qual è il costo di ciò? può essere correttamente misurato? (Rispetto all'esempio precedente)

Ad esempio:

public class A 
{ 
} 

public class B : A 
{ 
} 

var obj = new B(); 
var obj2 = (A)obj; // is this an "expensive" operation? this is not boxing 
+8

Non ci sono boxe coinvolti quando si esegue il cast da un tipo di riferimento all'altro. – BrokenGlass

+0

È misurabile in modo appropriato? dovrebbe essere evitato? –

+0

Mentre la boxe non è coinvolta quando si esegue il casting di un tipo di riferimento su un altro, la conversione potrebbe essere. La conversione di un tipo di riferimento in un altro tipo di riferimento non correlato potrebbe essere costoso. –

risposta

22

Sono curioso di sapere se tutte le conversioni in conseguenza C# nel pugilato.

No. Solo conversioni Boxing Risultato nel pugilato, da qui il nome "conversioni di pugilato". Conversioni boxe sono tutti incorporato nelle conversioni dai tipi di valore ai tipi di riferimento - sia a una classe ereditata dal tipo di valore, sia a un'interfaccia che implementa (oppure a un'interfaccia compatibile con un'interfaccia implementata tramite una conversione di riferimento covariante o controvariante).

convergono tutti opera un'operazione costosa?

conversioni No. identità sono costo zero perché il compilatore possa elide interamente.

Quali sono i costi delle conversioni di riferimento implicite ed esplicite?

Le conversioni implicite di riferimento sono a costo zero. Il compilatore può eliderli interamente. Cioè, la conversione da Giraffe al suo tipo di base Animal o Giraffe al suo tipo di interfaccia implementato IAmATallMammal, è gratuita.

Le conversioni di riferimento esplicite comportano un controllo di runtime per verificare che il riferimento faccia effettivamente riferimento a un oggetto del tipo desiderato.

Se il controllo di runtime è "costoso" o meno dipende dal budget.

tale costo può essere adeguatamente misurato?

Sicuro. Decidi quale risorsa è pertinente per te - il tempo, diciamo - e poi misura attentamente il tuo consumo di tempo con un cronometro.

Una domanda non ha chiesto, ma probabilmente dovrebbe avere:

Quali sono le conversioni più costosi?

conversioni definite dall'utente non sono altro che uno zucchero sintattico per una chiamata di metodo; quel metodo può richiedere arbitrariamente a lungo, come qualsiasi metodo.

Le conversioni dinamiche riavviano il compilatore in fase di runtime; il compilatore può impiegare arbitrariamente a lungo per eseguire un'analisi di tipo, a seconda di quanto sia difficile il problema di analisi che si sceglie di lanciare.

+1

Eric, che dire di una conversione implicita resa esplicita dal programmatore? Presumo che sia anche eluito dal compilatore. (Esempio: 'var o = (oggetto)" Some stringa "; return o.GetHashCode();') – phoog

+2

@phoog: corretto. Non c'è bisogno di generare IL per quello; il riferimento alla stringa è già assegnabile alla variabile. –

10

No.

inscatolamento significa mettere un valore in una nuova istanza tipo di riferimento.

Le trasmissioni standard tra tipi di riferimento non comportano alcuna assegnazione.
(calchi definiti dall'utente possono fare qualsiasi cosa)

+0

"La trasmissione da un tipo di riferimento non comporta alcuna allocazione." Non necessariamente vero. – jason

+0

@ Jason: Chiarito – SLaks

+0

Svincolato rimosso. – jason

7

Sono curioso di sapere se tutti i calchi in C risultato # nel pugilato,

No. La boxe è uno very special operation che significa trattare un caso di un tipo di valore come istanza di un tipo di riferimento. Per la conversione del tipo di riferimento alla conversione del tipo di riferimento, il concetto non ha alcun ruolo.

sono tutte operazioni costose?

Risposta breve: No.

Risposta lunga: Definire costosa. Ancora no, però.

E a proposito di trasmissioni da 2 tipi diversi di tipi di riferimento? qual è il costo di ciò?

Bene, cosa succede se si tratta solo di una conversione di riferimento derivata di base? È velocissimo perché non succede nulla.

Altre conversioni definite dall'utente potrebbero essere "lente", potrebbero essere "veloci".

Questo è "lento".

class A { public int Foo { get; set; } } 
class B { 
    public int Foo { get; set; } 
    static Random rg = new Random(); 
    static explicit operator A(B b) { 
     Thread.Sleep(rg.Next()); 
     return new A { Foo = b.Foo; } 
    } 
} 

Questo è "veloce".

class A { public int Foo { get; set; } } 
class B { 
    public int Foo { get; set; } 
    static Random rg = new Random(); 
    static explicit operator A(B b) { 
     return new A { Foo = b.Foo; } 
    } 
} 

var obj2 = (A)obj; // questo è un operazione "costoso"? questo non è il pugilato

No, è "economico."

+0

operazione costosa significa == se ho un algoritmo che implica il looping + casting (senza boxing), è più saggio progettarlo diversamente, o è un'operazione banale che non è considerata costosa in termini di prestazioni (in termini di tempo di esecuzione) –

+0

@liortal: dipende. Se sei preoccupato per le prestazioni, misuralo. – SLaks

+0

Sono interessato a capire come funziona più che preoccuparsi specificamente di un colpo di performance –