Null comparisons in C# 2.0

  • Thread starter Thread starter Christoph Nahr
  • Start date Start date
C

Christoph Nahr

Question: Will C# 2.0 offer a way to directly and reliably produce the
fastest MSIL null check, i.e. a single opcode?

The current C# compiler will emit this opcode automatically when
comparing a type against null that doesn't override operator==.
However, if the type does have its own equality operator that method
is called instead, which is of course much slower.

Since only a psychotic implementation of operator== would return a
different result for null checks than the default implementation, a
useful workaround to get fast code is to write ((object) obj == null).

Now I'm reading through the C# 2.0 specs and I see a problem. Inside a
template class or method, you can use (obj == null) if obj is of a
generic type. But obj might be a value type! The C# compiler will
support this special case but that means we can't use the (object)
cast anymore.

So what's the deal? Is there another way to check for null -- can we
perhaps call HasValue on arbitrary objects? Or is the C# compiler
going to be revised so that all "== null" and "!= null" expressions
are automatically mapped to the appropriate MSIL opcodes, even in the
presence of user-defined operators? That would be the best solution
IMO, as it would also simplify these operator methods.
 
Christoph,
Now I'm reading through the C# 2.0 specs and I see a problem. Inside a
template class or method, you can use (obj == null) if obj is of a
generic type. But obj might be a value type!

Unless you restrict the type parameter to be a reference type only.
I'm not sure it makes sense to compare to null if you allow the type
parameter to be a value type.

Or is the C# compiler
going to be revised so that all "== null" and "!= null" expressions
are automatically mapped to the appropriate MSIL opcodes, even in the
presence of user-defined operators?

Overloaded operators can't currently be used with generic type
parameters, because there are no constraint to enforce that the
operators are defined. So == on a variable of a generic parameter type
should always compile to a brtrue instruction. If you have

class Foo {
public static bool operator ==(Foo f1, Foo f2) {...}
public static bool operator !=(Foo f1, Foo f2) {...}
}

class Generic<T> where T : class {
void Bar(T t) {
if ( t == null ) ...
}
}

and use Generic<Foo>, the operators in Foo will not be used by the Bar
method.



Mattias
 
Unless you restrict the type parameter to be a reference type only.
I'm not sure it makes sense to compare to null if you allow the type
parameter to be a value type.

That's a special clause for generics: comparing an instance of an
unconstrained generic type that is a value type to null always returns
false, rather than throwing an exception.

(See section 20.8.4, "Reference equality operators", in the current
draft of the C# 2.0 Specifications)
Overloaded operators can't currently be used with generic type
parameters, because there are no constraint to enforce that the
operators are defined. So == on a variable of a generic parameter type
should always compile to a brtrue instruction.

Hmm, I think the compiler should use an overloaded parameter if a base
class constraint is specified (see sections 20.7.2 "Member lookup on
type parameters" and 20.9.2 "Member lookup").

But now that I'm reading these sections I see that *without* such a
constraint, the System.Object implementation will be used, and that
should indeed compile to brtrue as you said.

So it looks like C# 2.0 already does exactly what I want. :-) Thanks!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top