Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / December 2007

Tip: Looking for answers? Try searching our database.

conditional operator throws exceptions when casting

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Webbert - 03 Dec 2007 13:15 GMT
I wrote a little test to demonstrate.

Test 1 - should fail - can not cast null to an Int16
Test 2 - should result in the value 0 - one cast on the value returned
Test 3 - should result in the value 0 - cast on each return value
Test 4 - should result in the value 0 - normal cast
Test 5 - should result in the value 0 - Same as test 2 but hard coded

Any thoughts are appreciated.
Dave

============

Test 1: Failed: Object reference not set to an instance of an object.
Test 2: Failed: Specified cast is not valid.
Test 3: Successful: 0
Test 4: Successful: 0
Test 5: Successful: 0

============

using System;
using System.Data;
using System.Diagnostics;

namespace ConditionalCheck
{
    class Program
    {
        static void Main( string[] args )
        {
            bool rc;
            Int16 number;

            // Setup
            DataTable dt = new DataTable();
            dt.Columns.Add( new DataColumn( "port", typeof( Int16 ) ) );
            dt.Rows.Add();

            Debug.WriteLine( "\n\n\n" );
            Debug.WriteLine( "===================\n" );

            // Test
            object v = dt.Rows[0]["port"];

            try { number = (Int16)( ( v != DBNull.Value ) ? v : null );
Debug.WriteLine( "Test 1: Successful: " + number ); }
            catch ( Exception ex ) { Debug.WriteLine( "Test 1: Failed: " + ex.Message
); }

            try { number = (Int16)( ( v != DBNull.Value ) ? v : 0 ); Debug.WriteLine(
"Test 2: Successful: " + number ); }
            catch ( Exception ex ) { Debug.WriteLine( "Test 2: Failed: " + ex.Message
); }

            try { number = ( ( v != DBNull.Value ) ? (Int16)v : (Int16)0 );
Debug.WriteLine( "Test 3: Successful: " + number ); }
            catch ( Exception ex ) { Debug.WriteLine( "Test 3: Failed: " + ex.Message
); }

            number = 0;
            object y = number;
            try { number = (Int16)( y ); Debug.WriteLine( "Test 4: Successful: " +
number ); }
            catch ( Exception ex ) { Debug.WriteLine( "Test 4: Failed: " + ex.Message
); }

            rc = ( number ==  500 );
            try { number = (Int16)( ( rc ) ? 1 : 0 ); Debug.WriteLine( "Test 5:
Successful: " + number ); }
            catch ( Exception ex ) { Debug.WriteLine( "Test 5: Failed: " + ex.Message
); }

            Debug.WriteLine( "\n===================\n" );
        }
    }
}
Jon Skeet [C# MVP] - 03 Dec 2007 13:32 GMT
> I wrote a little test to demonstrate.
>
[quoted text clipped - 5 lines]
>
> Any thoughts are appreciated.

The problem is that the cast is being applied to "object", as that's
the type of v. Now, the cast is to Int16, but the literal 0 ends up as
a boxed Int32. It's equivalent to:

object o = 0;
Int16 x = (Int16) o;

which will also fail.

Change the literal to (Int16)0 and it should be okay.

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk

Webbert - 03 Dec 2007 16:47 GMT
Understood.

I guess I just don't understand why 0 (zero) is getting boxed to the type of
v before the cast.  I would have expected the literal type to be used.

Thanks,
Dave

> > I wrote a little test to demonstrate.
> >
[quoted text clipped - 16 lines]
>
> Change the literal to (Int16)0 and it should be okay.
Peter Duniho - 03 Dec 2007 17:59 GMT
> Understood.
>
> I guess I just don't understand why 0 (zero) is getting boxed to the  
> type of v before the cast.  I would have expected the literal type to be  
> used.

The literal type is used, just not when you are expecting it to.

The "?:" expression needs to have a single type.  The type is generated at  
compile time, and if you have two different types in the result operands  
for the operator, one needs to be implicitly castable by the compiler to  
the type of the other, with the type that winds up being suitable for the  
cast being applied to the whole expression.

Since the result operands have type "object" and type "Int32", and because  
Int32 is implicitly castable to object but object is not implicitly  
castable to Int32, the type of the whole expression is object and the  
Int32 parameter must be cast to object before evaluating the expression.  
The implicit cast simply boxes the Int32, which of course is cannot be  
successfully unboxed to an Int16.

As Jon says, you can resolve the issue by providing an explicit type for  
the literal by casting it to Int16.  That way when it gets boxed to suit  
the expression's overall type, it's a type that can be cast back to Int16.

Pete
Webbert - 03 Dec 2007 20:33 GMT
Jon/Peter,

Thanks for the input.

I have a tendency to want to know why.  The underlying piece that I was not
aware of was that the conditional operator needs to have a single type at
compile time.  With that in mind I understand exactly why the cast was
failing.

Perfectly clear now.

Thanks,
Dave

> > Understood.
> >
[quoted text clipped - 22 lines]
>
> Pete
Peter Duniho - 03 Dec 2007 20:47 GMT
> Jon/Peter,
>
> Thanks for the input.
>
> I have a tendency to want to know why.

An attitude like that should serve you well.  :)

> The underlying piece that I was not
> aware of was that the conditional operator needs to have a single type at
> compile time.

I thought as much.  It's a natural requirement IMHO, but not one that's  
necessarily obvious at first glance.  I've overlooked it myself in the  
past.  (It does become painfully obvious when the two result operands  
cannot be implicitly cast from one to the other, but it's harder to write  
code like that by accident. :) )

> With that in mind I understand exactly why the cast was
> failing.
>
> Perfectly clear now.

Excellent.  Glad to hear we could help!

Pete

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.