Pregunta

Estoy trabajando en un método de extensión que sólo es aplicable a los tipos de referencia. Creo, sin embargo, es actualmente el boxeo y unboxing del valor. ¿Cómo puedo evitar esto?

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);
        }
    }
}

Ejemplo de uso:

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

En algún método:

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
¿Fue útil?

Solución

Eso no es el boxeo. ¿dónde cree que es boxeo? Si es porque ha mirado la IL torno a "==", no deje que se le engañe - el JIT puede decidir qué hacer aquí. Tiene la posibilidad de generar código nativo diferente para cada uno (T, TResult) par. De hecho, el código será compartido por todos los tipos de referencia, y se diferencian de los tipos de valor. Así que terminarías 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)

Una vez dicho esto, si desea restringir su método de extensión a los tipos de referencia, hacerlo:

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

Todavía habrá una caja en el IL, pero no se preocupe - ocurra realmente ninguna boxeo. Después de todo, lo que podría be en caja? Usted está proporcionando una referencia, y las referencias a sí mismos no están en caja -. Los valores de tipo de valor sólo están en caja

Otros consejos

Simplemente, no hay nada en ese código que requeriría el boxeo. Hay son escenarios en los que el boxeo es inevitable, y también hay códigos de operación adicionales para cerrar la brecha entre el valor / tipos de árbitro ( constrained ) en algunos casos.

Pero no en este caso; sin real boxeo requerida (el JIT puede quitar algunos casos en forma de caja - pero no todos, por desgracia)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top