ATBG: guess the type

The latest episode of Coverity’s series Ask the Bug Guys is now posted on the Development Testing Blog. In this episode, a reader get me to play “guess the type”, and my colleague Tim talks a bit about the Java equivalent of the C# using statement for releasing resources. Check it out!

As always, if you have a question about an odd bit of C#, C, C++ or Java that led to a bug, send it to TheBugGuys@coverity.com; we'd love to see it. We can't guarantee an answer to all your problems, but we will pick a selection of the best questions and post about them on the dev testing blog.

About these ads

A contravariance conundrum

Suppose we have my usual hierarchy of types, Animal, Giraffe, etc, with the obvious type relationships. An IEqualityComparer<T> is contravariant in its type parameter; if we have a device which can compare two Animals for equality then it can compare two Giraffes for equality as well. So why does this code fail to compile?

IEqualityComparer<Animal> animalComparer = whatever;
IEnumerable<Giraffe> giraffes = whatever;
IEnumerable<Giraffe> distinct = giraffes.Distinct(animalComparer);

This illustrates a subtle and slightly unfortunate design choice in the method type inference algorithm, which of course was designed long before covariance and contravariance were added to the language.

Continue reading

Why does a foreach loop silently insert an “explicit” conversion?

The C# specification defines

foreach (V v in x) 
  embedded-statement

as having the same semantics as:[1. This is not exactly what the spec says; I've made one small edit because I don't want to get into the difference between the element type and the loop variable type in this episode.]

{
  E e = ((C)(x)).GetEnumerator();
  try 
  {
    V v;  // Inside the while in C# 5.
    while (e.MoveNext()) 
    {
      v = (V)e.Current;
      embedded-statement
    }
  }
  finally 
  {
    // necessary code to dispose e
  }
}

There are a lot of subtleties here that we've discussed before; what I want to talk about today is the explicit conversion from e.Current to V. On the face of it this seems very problematic; that's an explicit conversion. The collection could be a list of longs and V could be int; normally C# would not allow a conversion from long to int without a cast operator appearing in the source code.[2. Or the long being a constant that fits into an int.] What justifies this odd design choice?

Continue reading

Why not allow double/decimal implicit conversions?

I’ve talked a lot about floating point math over the years in this blog, but a quick refresher is in order for this episode.

A double represents a number of the form +/- (1 + F / 252 ) x 2E-1023, where F is a 52 bit unsigned integer and E is an 11 bit unsigned integer; that makes 63 bits and the remaining bit is the sign, zero for positive, one for negative. You'll note that there is no way to represent zero in this format, so by convention if F and E are both zero, the value is zero. (And similarly there are other reserved bit patterns for infinities, NaN and denormalized floats which we will not get into today.)

A decimal represents a number in the form +/- V / 10X where V is a 96 bit unsigned integer and X is an integer between 0 and 28.

Both are of course "floating point" because the number of bits of precision in each case is fixed, but the position of the decimal point can effectively vary as the exponent changes.
Continue reading

What the meaning of is is

Today a follow-up to my 2010 article about the meaning of the is operator. Presented as a dialog, as is my wont!

I've noticed that the is operator is inconsistent in C#. Check this out:

string s = null; // Clearly null is a legal value of type string
bool b = s is string; // But b is false!

What's up with that?

Let's suppose you and I are neighbours.

Um... ok, I'm not sure where this is going, but sure.

Continue reading

Static analysis of “is”

Returning now to the subject we started discussing last time on FAIC: sometimes the compiler can know via static analysis[1. That is, analysis done knowing only the compile-time types of expressions, rather than knowing their possibly more specific run-time types] that an is operator expression is guaranteed to produce a particular result.
Continue reading

An “is” operator puzzle, part one

It is possible for a program with some local variable x

bool b = x is FooBar;

to assign true to b at runtime, even though there is no conversion, implicit or explicit, from x to FooBar allowed by the compiler! That is to say that

FooBar foobar = (FooBar)x;

would not be allowed by the compiler in that same program.

Can you create a program to demonstrate this fact?

This is not a particularly hard puzzle but it does illustrate some of the subtleties of the is operator that we'll discuss in the next episode.

Representation and identity

(Note: not to be confused with Inheritance and Representation.)

I get a fair number of questions about the C# cast operator. The most frequent question I get is:

short sss = 123;
object ooo = sss;            // Box the short.
int iii = (int) sss;         // Perfectly legal.
int jjj = (int) (short) ooo; // Perfectly legal
int kkk = (int) ooo;         // Invalid cast exception?! Why?

Why? Because a boxed T can only be unboxed to T.[1. Or Nullable<T>.] Once it is unboxed, it’s just a value that can be cast as usual, so the double cast works just fine.
Continue reading