Strutture, interfacce e boxe

Possibile duplicato:
È sicuro che le strutture implementino le interfacce?

Prendi questo codice:

interface ISomeInterface { public int SomeProperty { get; } } struct SomeStruct : ISomeInterface { int someValue; public int SomeProperty { get { return someValue; } } public SomeStruct(int value) { someValue = value; } } 

e poi lo faccio da qualche parte:

 ISomeInterface someVariable = new SomeStruct(2); 

è il SomeStruct inscatolato in questo caso?

    Sì. Fondamentalmente ogni volta che hai bisogno di un riferimento e hai solo un valore di tipo valore, il valore è in scatola.

    Qui, ISomeInterface è un’interfaccia, che è un tipo di riferimento. Quindi il valore di someVariable è sempre un riferimento, quindi il valore della struct appena creato deve essere inserito.

    Il punto di Jon è vero, ma come nota a margine c’è una leggera eccezione alla regola; farmaci generici. Se si dispone di where T : ISomeInterface , questo è limitato e utilizza un opcode speciale . Ciò significa che l’interfaccia può essere utilizzata senza boxe. Per esempio:

     public static void Foo(T obj) where T : ISomeInterface { obj.Bar(); // Bar defined on ISomeInterface } 

    Questo non riguarda il pugilato, anche per il tipo di valore T Tuttavia, se (nello stesso Foo ) fai:

     ISomeInterface asInterface = obj; asInterface.Bar(); 

    poi quelle scatole come prima. Il vincolato si applica solo direttamente a T

    Sto aggiungendo questo per sperare di gettare un po ‘più di luce sulle risposte offerte da Jon e Marc.

    Considera questo metodo non generico:

     public static void SetToNull(ref ISomeInterface obj) { obj = null; } 

    Hmm … impostando un parametro ref su null. Questo è ansible solo per un tipo di riferimento, corretto? (Bene, o per un Nullable ; ma ignoriamo questo caso per mantenere le cose semplici.) Quindi il fatto che questo metodo compili ci dice che una variabile dichiarata come di un certo tipo di interfaccia deve essere trattata come un tipo di riferimento.

    La frase chiave qui è “dichiarato come”: considera questo tentativo di chiamare il metodo sopra riportato:

     var x = new SomeStruct(); // This line does not compile: // "Cannot convert from ref SomeStruct to ref ISomeInterface" -- // since x is declared to be of type SomeStruct, it cannot be passed // to a method that wants a parameter of type ref ISomeInterface. SetToNull(ref x); 

    Certo, il motivo per cui non è ansible passare x nel codice sopra a SetToNull è che x dovrebbe essere dichiarato come ISomeInterface per poter passare ref x – e non perché il compilatore sappia magicamente che SetToNull include la riga obj = null . Ma in un modo che rafforza il mio punto: la linea obj = null è legale proprio perché sarebbe illegale passare una variabile non dichiarata come ISomeInterface al metodo.

    In altre parole, se una variabile viene dichiarata come ISomeInterface , può essere impostata su null, pura e semplice. E questo perché le interfacce sono tipi di riferimento – quindi, dichiarando un object come un’interfaccia e assegnandolo a un tipo di valore caselle di oggetti che valgono.

    Ora, d’altra parte, considera questo ipotetico metodo generico:

     // This method does not compile: // "Cannot convert null to type parameter 'T' because it could be // a non-nullable value type. Consider using 'default(T)' instead." -- // since this method could take a variable declared as, eg, a SomeStruct, // the compiler cannot assume a null assignment is legal. public static void SetToNull(ref T obj) where T : ISomeInterface { obj = null; } 

    La documentazione MSDN ci dice che le strutture sono valore, non i tipi di riferimento. Sono in scatola quando si converte in / da una variabile di tipo object . Ma la domanda centrale qui è: che ne è di una variabile di un tipo di interfaccia? Dato che l’interfaccia può anche essere implementata da una class, allora questo deve essere equivalente alla conversione da un valore a un tipo di riferimento, come già detto da Jon Skeet, quindi si verificherà la boxe. Altre discussioni su un blog di msdn .