Domanda

Sto lavorando a un metodo di estensione che è applicabile solo ai tipi di riferimento. Penso, tuttavia, è attualmente boxing e unboxing il valore. Come posso evitare questo?

namespace System
{
    public static class SystemExtensions
    {
        public static TResult GetOrDefaultIfNull<T, TResult>(this T obj, Func<T, TResult> getValue, TResult defaultValue)
        {
            if (obj == null)
                return defaultValue;
            return getValue(obj);
        }
    }
}

Esempio di utilizzo:

public class Foo
{
    public int Bar { get; set; }
}

In un metodo:

Foo aFooObject = new Foo { Bar = 1 };
Foo nullReference = null;

Console.WriteLine(aFooObject.GetOrDefaultIfNull((o) => o.Bar, 0));  // results: 1
Console.WriteLine(nullReference.GetOrDefaultIfNull((o) => o.Bar, 0));  // results: 0
È stato utile?

Soluzione

Questo non è la boxe. Dove pensi che è di pugilato? Se è perché hai guardato il IL intorno "==", non lasciatevi ingannare - il JIT arriva a decidere cosa fare qui. Ha la possibilità di generare il codice nativo diverso per ogni (T, TResult) coppia. Infatti, il codice sarà condiviso per tutti i tipi di riferimento, e si differenziano per tipi di valori. Così ci si finisce con:

T = string, TResult = int (native code #1)
T = Stream, TResult = byte (native code #2)
T = string, TResult = byte (native code #2)
T = Stream, TResult = string (native code #3)

Detto questo, se si vuole restringere la metodo di estensione per i tipi di riferimento, fare così:

public static TResult GetOrDefaultIfNull<T, TResult>
    (this T obj, Func<T, TResult> getValue, TResult defaultValue)
    where T : class

Non ci sarà ancora una scatola nel IL, ma non preoccupatevi - non boxe sarà effettivamente manifestarsi. Dopo tutto, che potrebbero essere inscatolato? Si sta fornendo un punto di riferimento, e riferimenti stessi sono mai in scatola -. Solo valori di tipo valore sono boxed

Altri suggerimenti

Semplicemente, non c'è nulla in quel codice che richiederebbe la boxe. Ci sono scenari dove boxe è inevitabile, e ci sono anche codici operativi supplementari per colmare il divario tra valore / tipi ref ( constrained ) in alcuni casi.

Ma non in questo caso; senza reale Pugilato richiesto (JIT può rimuovere alcuni scatolata casi - ma non tutti, purtroppo)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top