Nullable types giving error

  • Thread starter Thread starter tshad
  • Start date Start date
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
 
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?" ?
 
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.
 
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
 
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
 
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
 
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"];
 
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
 
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.
 
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
 
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.)
 
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
 
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
 
(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.
 
Back
Top