Nullable types giving error

T

tshad

I have the following in c# VS 2005.

fn.ProjectTableID = dbReader["ProjectTableID"] == DBNull.Value ? null :
(int?)dbReader["ProjectTableID"];

This works fine as long as dbReader["ProjectTableID"] is null.

If it is a value I get an error:

Specified cast is not valid.

Why is that?

How do I assign the value?

I tried:

fn.ProjectTableID.Value = dbReader["ProjectTableID"] == DBNull.Value ?
null : (int?)dbReader["ProjectTableID"];

but that didn't work either.

Thanks,

Tom
 
J

Jon Skeet [C# MVP]

tshad said:
I have the following in c# VS 2005.

fn.ProjectTableID = dbReader["ProjectTableID"] == DBNull.Value ? null :
(int?)dbReader["ProjectTableID"];

This works fine as long as dbReader["ProjectTableID"] is null.

If it is a value I get an error:

Specified cast is not valid.

Why is that?

How do I assign the value?

I tried:

fn.ProjectTableID.Value = dbReader["ProjectTableID"] == DBNull.Value ?
null : (int?)dbReader["ProjectTableID"];

but that didn't work either.

Have you tried casting to "int" instead of "int?" ?
 
J

Jon Skeet [C# MVP]

tshad said:
I have the following in c# VS 2005.

fn.ProjectTableID = dbReader["ProjectTableID"] == DBNull.Value ? null :
(int?)dbReader["ProjectTableID"];

This works fine as long as dbReader["ProjectTableID"] is null.

If it is a value I get an error:

Specified cast is not valid.

Why is that?

How do I assign the value?

I tried:

fn.ProjectTableID.Value = dbReader["ProjectTableID"] == DBNull.Value ?
null : (int?)dbReader["ProjectTableID"];

but that didn't work either.

Ignore my previous response.

Find out what dbReader["ProjectTableID"].GetType() shows. I suspect it
won't be System.Int32.
 
T

tshad

Jon Skeet said:
tshad said:
I have the following in c# VS 2005.

fn.ProjectTableID = dbReader["ProjectTableID"] == DBNull.Value ? null :
(int?)dbReader["ProjectTableID"];

This works fine as long as dbReader["ProjectTableID"] is null.

If it is a value I get an error:

Specified cast is not valid.

Why is that?

How do I assign the value?

I tried:

fn.ProjectTableID.Value = dbReader["ProjectTableID"] ==
DBNull.Value ?
null : (int?)dbReader["ProjectTableID"];

but that didn't work either.

Have you tried casting to "int" instead of "int?" ?

Yes.

If I change it to:

fn.ProcessingType = dbReader["ProcessingType"] == DBNull.Value ? null
: (int)dbReader["ProcessingType"];

I get:

Type of conditional expression cannot be determined because there is no
implicit conversion between '<null>' and 'int'

Thanks,

Tom
 
T

tshad

Jon Skeet said:
tshad said:
I have the following in c# VS 2005.

fn.ProjectTableID = dbReader["ProjectTableID"] == DBNull.Value ? null :
(int?)dbReader["ProjectTableID"];

This works fine as long as dbReader["ProjectTableID"] is null.

If it is a value I get an error:

Specified cast is not valid.

Why is that?

How do I assign the value?

I tried:

fn.ProjectTableID.Value = dbReader["ProjectTableID"] ==
DBNull.Value ?
null : (int?)dbReader["ProjectTableID"];

but that didn't work either.

Ignore my previous response.

Find out what dbReader["ProjectTableID"].GetType() shows. I suspect it
won't be System.Int32.

It isn't.

It depends. The type in SQL is tinyint. In my record fn.ProjectTableID is
an "int?". The value will either be null or a number from 1-25.

If it is null, which is the case for the first 12 records, I get the
following in the debugger watch window

{Name = "DBNull" FullName = "System.DBNull"} System.Type
{System.RuntimeType}

:If it is a value like 10, I get:

{Name = "Byte" FullName = "System.Byte"} System.Type {System.RuntimeType}

I would assume that I would be casting it to either int? or int since I am
putting it in an int? field. I can't change the fn.ProjectTableID to int
(or byte) as it can be null and I need to keep track of that.

Thanks,

Tom
 
K

Kalpesh

tshad,

I am guessing that fn.ProcessingType is of type nullable int.
See if this works

fn.ProcessingType = dbReader["ProcessingType"] == DBNull.Value ?
(int?)0
: (int)dbReader["ProcessingType"];

Does that work?

Kalpesh
 
K

Kalpesh

My bad.
I am not too good with the concept of nullable type

Either above or this should work.

fn.ProcessingType = dbReader["ProcessingType"] == DBNull.Value ?
(int?)0
: (int?)dbReader["ProcessingType"];
 
A

Arne Vajhøj

tshad said:
It depends. The type in SQL is tinyint. In my record fn.ProjectTableID is
an "int?". The value will either be null or a number from 1-25.

If it is null, which is the case for the first 12 records, I get the
following in the debugger watch window

{Name = "DBNull" FullName = "System.DBNull"} System.Type
{System.RuntimeType}

:If it is a value like 10, I get:

{Name = "Byte" FullName = "System.Byte"} System.Type {System.RuntimeType} ^^^^^^^^^^^

I would assume that I would be casting it to either int? or int since I am
putting it in an int? field. I can't change the fn.ProjectTableID to int
(or byte) as it can be null and I need to keep track of that.

Try cast it to byte.

Arne
 
J

Jon Skeet [C# MVP]

It isn't.

It depends. The type in SQL is tinyint. In my record fn.ProjectTableID is
an "int?". The value will either be null or a number from 1-25.

If it is null, which is the case for the first 12 records, I get the
following in the debugger watch window

{Name = "DBNull" FullName = "System.DBNull"} System.Type
{System.RuntimeType}

:If it is a value like 10, I get:

{Name = "Byte" FullName = "System.Byte"} System.Type {System.RuntimeType}

Right - that's the important part.
I would assume that I would be casting it to either int? or int since I am
putting it in an int? field.

The important thing is what you're casting. You're trying to unbox,
which means the type has to be right. You can cast it to byte? (or
indeed byte) and it'll be fine. Cast the null to int? so that compiler
knows what to make the overall expression type.
 
T

tshad

Arne Vajhøj said:
Try cast it to byte.

That works fine.

Since a tinyint ranges from 0 to 255, I assume that is why it is assumed to
be a byte.

fn.ProcessingType = dbReader["ProcessingType"] == DBNull.Value ? null :
(byte?)dbReader["ProcessingType"];

This works ok

I would have assumed that int would also work but I guess not.

Thanks,

Tom
 
J

Jon Skeet [C# MVP]

That works fine.

Since a tinyint ranges from 0 to 255, I assume that is why it is assumed to
be a byte.

fn.ProcessingType = dbReader["ProcessingType"] == DBNull.Value ? null :
(byte?)dbReader["ProcessingType"];

This works ok

I would have assumed that int would also work but I guess not.

No, because you're unboxing. When you unbox, you have to specify the
correct type, not just one which the correct type can be implicitly
converted to.

(You can also specify the nullable version of the correct type.)
 
A

Arne Vajhøj

tshad said:
Arne Vajhøj said:
Try cast it to byte.

That works fine.

Since a tinyint ranges from 0 to 255, I assume that is why it is assumed to
be a byte.

fn.ProcessingType = dbReader["ProcessingType"] == DBNull.Value ? null :
(byte?)dbReader["ProcessingType"];

This works ok

I would have assumed that int would also work but I guess not.

Maybe you will find this code snippet illustrative:

using System;

namespace E
{
public class Program
{
public static void Main(string[] args)
{
byte b = 123;
object o = b;
Console.WriteLine("Cast to byte works: " + (byte)o);
try{
Console.WriteLine("Cast to int works: " + (int)o);
}
catch
{
Console.WriteLine("Cast to int did not work");
}
Console.WriteLine("Cast to byte cast to int works: " + (int)(byte)o);
Console.ReadKey();
}
}
}

Arne
 
T

tshad

Arne Vajhøj said:
tshad said:
Arne Vajhøj said:
tshad wrote:
It depends. The type in SQL is tinyint. In my record
fn.ProjectTableID is an "int?". The value will either be null or a
number from 1-25.

If it is null, which is the case for the first 12 records, I get the
following in the debugger watch window

{Name = "DBNull" FullName = "System.DBNull"} System.Type
{System.RuntimeType}

:If it is a value like 10, I get:

{Name = "Byte" FullName = "System.Byte"} System.Type
{System.RuntimeType}
^^^^^^^^^^^
I would assume that I would be casting it to either int? or int since I
am putting it in an int? field. I can't change the fn.ProjectTableID
to int (or byte) as it can be null and I need to keep track of that.
Try cast it to byte.

That works fine.

Since a tinyint ranges from 0 to 255, I assume that is why it is assumed
to be a byte.

fn.ProcessingType = dbReader["ProcessingType"] == DBNull.Value ? null :
(byte?)dbReader["ProcessingType"];

This works ok

I would have assumed that int would also work but I guess not.

Maybe you will find this code snippet illustrative:

using System;

namespace E
{
public class Program
{
public static void Main(string[] args)
{
byte b = 123;
object o = b;
Console.WriteLine("Cast to byte works: " + (byte)o);
try{
Console.WriteLine("Cast to int works: " + (int)o);
}
catch
{
Console.WriteLine("Cast to int did not work");
}
Console.WriteLine("Cast to byte cast to int works: " + (int)(byte)o);
Console.ReadKey();
}
}
}

(int)(byte)o

So what you did here was unbox the object and then implicitly convert it to
int?

And why is dbReader["ProcessingType"] considered boxed?

Thanks,

Tom
 
J

Jon Skeet [C# MVP]

(int)(byte)o

So what you did here was unbox the object and then implicitly convert it to
int?

Well, explicitly convert it to int - but yes.
And why is dbReader["ProcessingType"] considered boxed?

Because its return type is "object" - i.e. it will return a reference,
so the only way of returning value type data is to return a boxed form.
 

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

Similar Threads


Top