Why can I check generic for null when it may be invalid or cannot be an object?

When writing a class that contains a shared variable

public class ServiceInvoker<TService> : IDisposable { private TService _Service; public ServiceInvoker() { _Service = Activator.CreateInstance<TService>(); } public void Invoke(Action<TService> action) { // CAN use null if (_Service == null) throw new ObjectDisposedException("ServiceInvoker"); .... } public void Dispose() { // CAN'T use null this._Service = default(TService); } } 

I noticed that the compiler allows me to check the null value on a shared variable, but this, of course, does not allow me to set null, so we should use default(TService) .

Should the compiler notify me that I am using null? Or does he use box to object conversion to run a test for null here?

I read about the correct zero score for the general , but I am interested to know why, and not just how.

+7
source share
4 answers

Why can I check generic for null when it may be invalid or cannot be an object?

The question is unconvincing; the value of any generic type expression will always be either an object or a null reference at run time. I think you wanted to ask:

Why can I check what is common to null when its runtime type cannot be either a null value type or a reference type?

The C # specification ensures that comparing equality with literal zero is legal in section 7.6.10, which I quote here for your convenience:


If an operand of type T is compared to NULL and the runtime type T is value type, the result of the comparison is false. [...] The construction x == null allowed, even if T can represent the type of value, and the result is simply defined as false when T is the type of value.


Please note that there is a small mistake; the last sentence should end with "type with a zero value".

I am never sure if I really answered the question β€œwhy?”. The question is satisfactory or not. If this is not satisfactory, try asking a more specific question.

Should the compiler notify me that I am using null?

Not. Why do you think the compiler should warn you about using the language function correctly?

Does it use box-to-object conversion to perform a check for null here?

Well, this is a bit of a difficult point. On the one hand, section 7.6.10 states:


The predefined reference type equality operators never give rise to boxing operations for their operands. It would be pointless to perform such boxing operations, since links to newly selected nested instances will necessarily be different from all other links.


However, when we generate IL to compare the total T with NULL, we certainly do generate the T field, the load is null, and the comparison. Jitter can be smart enough to rule out the actual distribution of memory in a box; if T is a reference type, then it does not need a box, if it is a type of values ​​with a null value, then it could be turned into a call to check the HasValue property, and if it is a value type that is not null, then boxing and checking can be turned into a simple generation of "false". I don't know exactly what the various jit compiler implementations actually do; if you're interested, check and see!

+11
source

The CLR knows that a value type that cannot be nullable can never be null, so it always always returns false . Is that what you are asking?

+4
source

This compiles, although with a warning:

 int l = 0; if (l == null) { //whatever } 

A warning:

  warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?' 

So this works, albeit with not very useful results. However, in general, this can be a useful test.

+1
source

Do you think the compiler should warn you? The compiler will give warnings when you use something like this:

 if (1 == 2) //always false if (Dog is Cat) //never true 

But in this case, the condition can be true (when the TService is a type of refernece and is null) or false (when it is a value type or a reference type, but not null). It perfectly represents the use of the if statement (sometimes true and sometimes false).

+1
source

All Articles