public void DoFoo<T>(T foo) where T : ISomeInterface<T>
{
//possible compare of value type with 'null'.
if (foo == null) throw new ArgumentNullException("foo");
}
I'm purposely only checking against null because I don't want to restrict a ValueType
from being equal to its default(T)
. My code compiles and works just fine this way (ReSharper complains, but not CodeAnalysis). Though I do wonder:
- Is there a more standard way to handle this situation?
- Is there any chance of an issue arrising from this?
- What truly happens under the hood when I make a call and pass in a value type?
That is a good insight, but don't worry, you are already covered there. It is not legal to compare a T against
default(T)
using==
in the first place; overload resolution will not find a unique best==
operator.Of course, you could do the comparison with
.Equals
but then you run the risk of crashing if the receiver is null, which is precisely what you are attempting to avoid.No. Comparing to null is the right thing to do here.
As the C# specification says in section 7.10.6: "The
x == null
construct is permitted even though T could represent a value type, and the result is simply defined to be false when T is a value type."Sure. Just because code compiles does not mean that it has the semantics you intend. Write some tests.
The question is ambiguous. Let me rephrase it into two questions:
The jitter compiles the method on the first invocation with that construction. When the jitter detects the null check, it replaces it with "false" because it knows that no non-nullable value type will ever be equal to null.
In that case the jitter cannot elide the null check and the call site cannot avoid the boxing. The SFoo instance will be boxed, and the reference to the boxed SFoo will be checked to see if it is null.