I'm working on an extension method that's only applicable to reference types. I think, however, it's currently boxing and unboxing the the value. How can I avoid this?
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);
}
}
}
Example usage:
public class Foo
{
public int Bar { get; set; }
}
In some method:
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
That's not boxing. Where do you think it is boxing? If it's because you've looked at the IL around "==", don't let it fool you - the JIT gets to decide what to do here. It has the chance to generate different native code for each (T
, TResult
) pair. In fact, the code will be shared for all reference types, and differ for value types. So you'd end up with:
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)
Having said that, if you want to restrict your extension method to reference types, do so:
public static TResult GetOrDefaultIfNull<T, TResult>
(this T obj, Func<T, TResult> getValue, TResult defaultValue)
where T : class
There'll still be a box in the IL, but don't worry - no boxing will actually occur. After all, what could be boxed? You're providing a reference, and references themselves are never boxed - only value type values are boxed.