Implicit Type Casting – The Is Question

I’ll start this post with an example:

public class MyClass
{
    private int m_HeldInteger = 0;

    public MyClass()
    {
    }

    public static implicit operator int(MyClass myClass)
    {
        return myClass.m_HeldInteger;
    }

    public static void Main(string[] args)
    {
        MyClass c = new MyClass();

        bool b = c is int;
    }
}

What have we here? We have the type MyClass which holds an integer field and has an implicit conversion to an integer.

Now let’s look at the Main method. In it, we instantiate the variable c to be of type MyClass. We then inquire the runtime to whether c is of type int or any of its descendants.
It’s pretty obvious that the answer will be no, so we will get a false assigned to the boolean variable b.

What I find wrong with this is that, effectively, c could indeed be of type int, because we can implicitly convert it to that type.
In this particular case, the compiler chooses to not translate our object to int prior to the execution of this expression, causing it to always return false. Was I to explicitly cast c into int, no exception would be thrown (since a call would be made to the implicit operator) and the value returned would be true.
This is correct behavior because, yes, the object c is indeed not of type int. On the other hand, this is not correct beahvior, since it could be of type int.

What do you think? Should this stay like it is or should it be changed?

Advertisements

5 thoughts on “Implicit Type Casting – The Is Question

  1. After reading through that code, I actually felt dirty for some reason.

    I don’t think that it should be changed because even though MyClass can return an int, MyClass is not derived from or related to int in any way.

    Besides, don’t we already have a .NET standard for returning reference types and the like: .ToXXX? (i.e. MyClass.ToInteger, MyClass.ToString, MyClass.ToInfinityAndBeyond)

  2. I would have to vote for keeping the current "is" behaviour the same. The fact that MyClass can be "converted" to an int doesn’t mean it "is" an int, anymore than object.ToString() means that every object is a string. I see it as a difference between inheritance and composition, where MyClass is using the latter and operator overloading is just providing some optional syntactic niceties (for the languages that support it) in the same way that you might want to overload * in addition to providing a Multiply method.

  3. "is" is a natural counterpart to the "as" operator. In other words, as I understand it, "is" returns true if the corresponding conversion, using "as", will return a non-null value.

    Because "as" ignores user-defined conversions, it seems sensible that "is" should also ignore user-defined conversions.

    To do what you want, it would be handy if there was a method on the Type class that worked like this:

    if (someType.IsConvertableTo(someOtherType))

    It could even take a second param to say what kinds of conversions it should consider (e.g. user-defined implict only, all user defined conversions etc). I’m surprised that such method does not exist already. (Or maybe it does, but I just haven’t spotted it yet.)

  4. Although it might seems awkward to use an explicit cast, I think it is more correct then the implicit cast being in effect automatically.

  5. As much as I figure it, type safety defines teh elimination of implicit casting because of their unreadability. The method you define as an "implicit cast" is not, for that matter, an implicit cast – its indeed a very explicit cast.

    Allowing "is" to operate like that, would be to allow the horrible implicit cast back to our programming world, and allowing such automatic casts to be called up when we call operators, constructors and assignments.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s