Pergunta

Estou trabalhando em um método de extensão aplicável apenas aos tipos de referência. Eu acho que, no entanto, está atualmente boxe e dividindo o valor. Como posso evitar isso?

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

Exemplo de uso:

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

Em algum 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
Foi útil?

Solução

Isso não é boxe. Onde você acha isso é boxe? Se é porque você olhou para o IL em torno de "==", não deixe isso enganar você - o jit decide o que fazer aqui. Tem a chance de gerar código nativo diferente para cada um (T, TResult) par. De fato, o código será compartilhado para todos os tipos de referência e difere para os tipos de valor. Então você acabaria com:

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)

Dito isto, se você deseja restringir seu método de extensão aos tipos de referência, faça -o:

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

Ainda haverá uma caixa na IL, mas não se preocupe - nenhum boxe realmente ocorrerá. Afinal, o que poderia estar em caixa? Você está fornecendo uma referência e as próprias referências nunca são encaixotadas - apenas os valores do tipo de valor são encaixotados.

Outras dicas

Simplesmente, não há nada nesse código que exigiria boxe. Lá são Cenários em que o boxe é inevitável e também existem códigos opciais adicionais para a ponte da lacuna entre os tipos de valor/ref (constrained) em alguns casos.

Mas não neste caso; não real O boxe necessário (o JIT pode remover alguns estojos em forma de caixa - mas não tudo, infelizmente)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top