Formatting A String As Currency

S

Scott M.

Ok, this is driving me nuts...

I am using VS.NET 2003 and trying to take an item out of a row in a
loosely-typed dataset and place it in a label as a currency. As it is now,
I am getting my unformatted data values (as decimals) just fine, so I know
there's not a problem with the data retrieval, just the formatting.

I have read that this would work:

lblPrice.Text = prodRow["Price"].ToString("C");

But, I get errors indicating that ToString does not have any overloadable
methods that take any arguments.

I have tried these:

lblTotal.Text = String.Format("{0:c}", prodRow["Total"]);
lblTotal.Text = String.Format("{0:c}", prodRow["Total"].ToString());
lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

and each just returns the number, but not formatted as a currency.

I suspect the problem is that I am getting the data from a loosely-typed
dataset in the first place because I dropped this test code into my page and
it works just fine:

double price = 4.56;
lblTax.Text = String.Format("{0:c}", price);

Here's my original code that does produce my data (just not formatted):

DataRow prodRow = ds.Tables[0].Rows[0];
lblPriceEach.Text = prodRow["RetailPrice"].ToString();
lblPriceAll.Text = prodRow["PriceAll"].ToString();
lblTax.Text = prodRow["Tax"].ToString();
lblTotal.Text = prodRow["Total"].ToString();

I've even tried this (after putting the unformatted data into the label):

lblTotal.Text = String.Format("{0:c}", lblTotal.Text);

But, this just produces the raw number, without any formatting.

What am I not doing or doing wrong?!

Thanks
 
D

Dave Sexton

Hi Scott,

Can you verify that prodRow["Total"] is returning a numeric data type such as
System.Decimal, but not System.String?

The formatting, "0:C" won't work with the string Type.
 
S

Scott M.

Hi Dave,

prodRow["Total"] returns an object (loosely typed dataset item).

I suspected that the formatting wouldn't work with the String type, so I
tried (as posted):

lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

In the end, I should have been using the Convert class, which solved my
problem.

Thanks,

Scott


Dave Sexton said:
Hi Scott,

Can you verify that prodRow["Total"] is returning a numeric data type such
as System.Decimal, but not System.String?

The formatting, "0:C" won't work with the string Type.

--
Dave Sexton

Scott M. said:
Ok, this is driving me nuts...

I am using VS.NET 2003 and trying to take an item out of a row in a
loosely-typed dataset and place it in a label as a currency. As it is
now, I am getting my unformatted data values (as decimals) just fine, so
I know there's not a problem with the data retrieval, just the
formatting.

I have read that this would work:

lblPrice.Text = prodRow["Price"].ToString("C");

But, I get errors indicating that ToString does not have any overloadable
methods that take any arguments.

I have tried these:

lblTotal.Text = String.Format("{0:c}", prodRow["Total"]);
lblTotal.Text = String.Format("{0:c}", prodRow["Total"].ToString());
lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

and each just returns the number, but not formatted as a currency.

I suspect the problem is that I am getting the data from a loosely-typed
dataset in the first place because I dropped this test code into my page
and it works just fine:

double price = 4.56;
lblTax.Text = String.Format("{0:c}", price);

Here's my original code that does produce my data (just not formatted):

DataRow prodRow = ds.Tables[0].Rows[0];
lblPriceEach.Text = prodRow["RetailPrice"].ToString();
lblPriceAll.Text = prodRow["PriceAll"].ToString();
lblTax.Text = prodRow["Tax"].ToString();
lblTotal.Text = prodRow["Total"].ToString();

I've even tried this (after putting the unformatted data into the label):

lblTotal.Text = String.Format("{0:c}", lblTotal.Text);

But, this just produces the raw number, without any formatting.

What am I not doing or doing wrong?!

Thanks
 
D

Dave Sexton

Hi Scott,
prodRow["Total"] returns an object (loosely typed dataset item).

But the object returned is probably System.String, and that's what I was
asking. You can quickly verify this in a debugger watch window.
I suspected that the formatting wouldn't work with the String type, so I
tried (as posted):

lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

I suspect that will throw an InvalidCastException because prodRow["Total"] is
returning System.String, not System.Decimal.
In the end, I should have been using the Convert class, which solved my
problem.

Yes, the following should work:

lblTotal.Text = Convert.ToDecimal(prodRow["Total"]).ToString("C");

FYI, you might prefer to use a strong-typed DataSet so that the following code
could be used instead:

lblTotal.Text = prodRow.Total.ToString("C");

HTH

--
Dave Sexton

Scott M. said:
Hi Dave,

prodRow["Total"] returns an object (loosely typed dataset item).

I suspected that the formatting wouldn't work with the String type, so I
tried (as posted):

lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

In the end, I should have been using the Convert class, which solved my
problem.

Thanks,

Scott


Dave Sexton said:
Hi Scott,

Can you verify that prodRow["Total"] is returning a numeric data type such
as System.Decimal, but not System.String?

The formatting, "0:C" won't work with the string Type.

--
Dave Sexton

Scott M. said:
Ok, this is driving me nuts...

I am using VS.NET 2003 and trying to take an item out of a row in a
loosely-typed dataset and place it in a label as a currency. As it is
now, I am getting my unformatted data values (as decimals) just fine, so I
know there's not a problem with the data retrieval, just the formatting.

I have read that this would work:

lblPrice.Text = prodRow["Price"].ToString("C");

But, I get errors indicating that ToString does not have any overloadable
methods that take any arguments.

I have tried these:

lblTotal.Text = String.Format("{0:c}", prodRow["Total"]);
lblTotal.Text = String.Format("{0:c}", prodRow["Total"].ToString());
lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

and each just returns the number, but not formatted as a currency.

I suspect the problem is that I am getting the data from a loosely-typed
dataset in the first place because I dropped this test code into my page
and it works just fine:

double price = 4.56;
lblTax.Text = String.Format("{0:c}", price);

Here's my original code that does produce my data (just not formatted):

DataRow prodRow = ds.Tables[0].Rows[0];
lblPriceEach.Text = prodRow["RetailPrice"].ToString();
lblPriceAll.Text = prodRow["PriceAll"].ToString();
lblTax.Text = prodRow["Tax"].ToString();
lblTotal.Text = prodRow["Total"].ToString();

I've even tried this (after putting the unformatted data into the label):

lblTotal.Text = String.Format("{0:c}", lblTotal.Text);

But, this just produces the raw number, without any formatting.

What am I not doing or doing wrong?!

Thanks
 
C

Cor Ligthert [MVP]

Dave,

In my idea was Scott this implicitly telling, therefore your catch was in my
idea the right one.

Cor

Dave Sexton said:
Hi Scott,
prodRow["Total"] returns an object (loosely typed dataset item).

But the object returned is probably System.String, and that's what I was
asking. You can quickly verify this in a debugger watch window.
I suspected that the formatting wouldn't work with the String type, so I
tried (as posted):

lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

I suspect that will throw an InvalidCastException because prodRow["Total"]
is returning System.String, not System.Decimal.
In the end, I should have been using the Convert class, which solved my
problem.

Yes, the following should work:

lblTotal.Text = Convert.ToDecimal(prodRow["Total"]).ToString("C");

FYI, you might prefer to use a strong-typed DataSet so that the following
code could be used instead:

lblTotal.Text = prodRow.Total.ToString("C");

HTH

--
Dave Sexton

Scott M. said:
Hi Dave,

prodRow["Total"] returns an object (loosely typed dataset item).

I suspected that the formatting wouldn't work with the String type, so I
tried (as posted):

lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

In the end, I should have been using the Convert class, which solved my
problem.

Thanks,

Scott


Dave Sexton said:
Hi Scott,

Can you verify that prodRow["Total"] is returning a numeric data type
such as System.Decimal, but not System.String?

The formatting, "0:C" won't work with the string Type.

--
Dave Sexton

Ok, this is driving me nuts...

I am using VS.NET 2003 and trying to take an item out of a row in a
loosely-typed dataset and place it in a label as a currency. As it is
now, I am getting my unformatted data values (as decimals) just fine,
so I know there's not a problem with the data retrieval, just the
formatting.

I have read that this would work:

lblPrice.Text = prodRow["Price"].ToString("C");

But, I get errors indicating that ToString does not have any
overloadable methods that take any arguments.

I have tried these:

lblTotal.Text = String.Format("{0:c}", prodRow["Total"]);
lblTotal.Text = String.Format("{0:c}", prodRow["Total"].ToString());
lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

and each just returns the number, but not formatted as a currency.

I suspect the problem is that I am getting the data from a
loosely-typed dataset in the first place because I dropped this test
code into my page and it works just fine:

double price = 4.56;
lblTax.Text = String.Format("{0:c}", price);

Here's my original code that does produce my data (just not formatted):

DataRow prodRow = ds.Tables[0].Rows[0];
lblPriceEach.Text = prodRow["RetailPrice"].ToString();
lblPriceAll.Text = prodRow["PriceAll"].ToString();
lblTax.Text = prodRow["Tax"].ToString();
lblTotal.Text = prodRow["Total"].ToString();

I've even tried this (after putting the unformatted data into the
label):

lblTotal.Text = String.Format("{0:c}", lblTotal.Text);

But, this just produces the raw number, without any formatting.

What am I not doing or doing wrong?!

Thanks
 
J

JTC ^..^

Cor said:
Dave,

In my idea was Scott this implicitly telling, therefore your catch was in my
idea the right one.

Cor

Dave Sexton said:
Hi Scott,
prodRow["Total"] returns an object (loosely typed dataset item).
But the object returned is probably System.String, and that's what I was
asking. You can quickly verify this in a debugger watch window.
I suspected that the formatting wouldn't work with the String type, so I
tried (as posted):

lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);
I suspect that will throw an InvalidCastException because prodRow["Total"]
is returning System.String, not System.Decimal.
In the end, I should have been using the Convert class, which solved my
problem.
Yes, the following should work:

lblTotal.Text = Convert.ToDecimal(prodRow["Total"]).ToString("C");

FYI, you might prefer to use a strong-typed DataSet so that the following
code could be used instead:

lblTotal.Text = prodRow.Total.ToString("C");

HTH

--
Dave Sexton

Scott M. said:
Hi Dave,

prodRow["Total"] returns an object (loosely typed dataset item).

I suspected that the formatting wouldn't work with the String type, so I
tried (as posted):

lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

In the end, I should have been using the Convert class, which solved my
problem.

Thanks,

Scott


Hi Scott,

Can you verify that prodRow["Total"] is returning a numeric data type
such as System.Decimal, but not System.String?

The formatting, "0:C" won't work with the string Type.

--
Dave Sexton

Ok, this is driving me nuts...

I am using VS.NET 2003 and trying to take an item out of a row in a
loosely-typed dataset and place it in a label as a currency. As it is
now, I am getting my unformatted data values (as decimals) just fine,
so I know there's not a problem with the data retrieval, just the
formatting.

I have read that this would work:

lblPrice.Text = prodRow["Price"].ToString("C");

But, I get errors indicating that ToString does not have any
overloadable methods that take any arguments.

I have tried these:

lblTotal.Text = String.Format("{0:c}", prodRow["Total"]);
lblTotal.Text = String.Format("{0:c}", prodRow["Total"].ToString());
lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

and each just returns the number, but not formatted as a currency.

I suspect the problem is that I am getting the data from a
loosely-typed dataset in the first place because I dropped this test
code into my page and it works just fine:

double price = 4.56;
lblTax.Text = String.Format("{0:c}", price);

Here's my original code that does produce my data (just not formatted):

DataRow prodRow = ds.Tables[0].Rows[0];
lblPriceEach.Text = prodRow["RetailPrice"].ToString();
lblPriceAll.Text = prodRow["PriceAll"].ToString();
lblTax.Text = prodRow["Tax"].ToString();
lblTotal.Text = prodRow["Total"].ToString();

I've even tried this (after putting the unformatted data into the
label):

lblTotal.Text = String.Format("{0:c}", lblTotal.Text);

But, this just produces the raw number, without any formatting.

What am I not doing or doing wrong?!

Thanks

To add my two cent, the following will work ....

string price = "2.02";
this.textBox1.Text = String.Format("{0:C}", double.Parse(price));
 
D

Dave Sexton

Hi Cor,

Thanks, but Scott has not given me any reason to believe that he's aware
prodRow["Total"] is of the type System.String, not System.Decimal.

He did, after all, try to explain that it returns System.Object and then tried
to cast it to System.Decimal, claiming that it didn't work. That's an
indication, IMO, that he doesn't realize System.String can't be explicitly
cast to System.Decimal or that he doesn't realize prodRow["Total"] is not
returning System.Decimal, but probably System.String.

I've been trying to "explicitly" confirm what you believe was implied, since
my original response :)

--
Dave Sexton

Cor Ligthert said:
Dave,

In my idea was Scott this implicitly telling, therefore your catch was in my
idea the right one.

Cor

Dave Sexton said:
Hi Scott,
prodRow["Total"] returns an object (loosely typed dataset item).

But the object returned is probably System.String, and that's what I was
asking. You can quickly verify this in a debugger watch window.
I suspected that the formatting wouldn't work with the String type, so I
tried (as posted):

lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

I suspect that will throw an InvalidCastException because prodRow["Total"]
is returning System.String, not System.Decimal.
In the end, I should have been using the Convert class, which solved my
problem.

Yes, the following should work:

lblTotal.Text = Convert.ToDecimal(prodRow["Total"]).ToString("C");

FYI, you might prefer to use a strong-typed DataSet so that the following
code could be used instead:

lblTotal.Text = prodRow.Total.ToString("C");

HTH

--
Dave Sexton

Scott M. said:
Hi Dave,

prodRow["Total"] returns an object (loosely typed dataset item).

I suspected that the formatting wouldn't work with the String type, so I
tried (as posted):

lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

In the end, I should have been using the Convert class, which solved my
problem.

Thanks,

Scott


Hi Scott,

Can you verify that prodRow["Total"] is returning a numeric data type
such as System.Decimal, but not System.String?

The formatting, "0:C" won't work with the string Type.

--
Dave Sexton

Ok, this is driving me nuts...

I am using VS.NET 2003 and trying to take an item out of a row in a
loosely-typed dataset and place it in a label as a currency. As it is
now, I am getting my unformatted data values (as decimals) just fine, so
I know there's not a problem with the data retrieval, just the
formatting.

I have read that this would work:

lblPrice.Text = prodRow["Price"].ToString("C");

But, I get errors indicating that ToString does not have any
overloadable methods that take any arguments.

I have tried these:

lblTotal.Text = String.Format("{0:c}", prodRow["Total"]);
lblTotal.Text = String.Format("{0:c}", prodRow["Total"].ToString());
lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

and each just returns the number, but not formatted as a currency.

I suspect the problem is that I am getting the data from a loosely-typed
dataset in the first place because I dropped this test code into my page
and it works just fine:

double price = 4.56;
lblTax.Text = String.Format("{0:c}", price);

Here's my original code that does produce my data (just not formatted):

DataRow prodRow = ds.Tables[0].Rows[0];
lblPriceEach.Text = prodRow["RetailPrice"].ToString();
lblPriceAll.Text = prodRow["PriceAll"].ToString();
lblTax.Text = prodRow["Tax"].ToString();
lblTotal.Text = prodRow["Total"].ToString();

I've even tried this (after putting the unformatted data into the
label):

lblTotal.Text = String.Format("{0:c}", lblTotal.Text);

But, this just produces the raw number, without any formatting.

What am I not doing or doing wrong?!

Thanks
 
S

Scott M.

lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);
I suspect that will throw an InvalidCastException because prodRow["Total"]
is returning System.String, not System.Decimal.

No, it doesn't throw an exception, it just produces my (correct) data, but
without the currency formatting.

In the end, I should have been using the Convert class, which solved my
problem.

Yes, the following should work:

lblTotal.Text = Convert.ToDecimal(prodRow["Total"]).ToString("C");

No, that doesn't work for me. And, this is something I mentioned in my OP.
When I try to pass the "C" argument to the ToString method, I get a build
error indicating that there is no ToString method that takes 1 argument.

What did work for me was this:

lblTotal.Text = String.Format("{0:c}",Convert.ToDecimal(prodRow["Total"]));
FYI, you might prefer to use a strong-typed DataSet so that the following
code could be used instead:

Yes, I am aware of the benefits of strongly-typed datasets, but in this case
it is not an option.

Thanks.
 
S

Scott M.

Dave Sexton said:
Hi Cor,

Thanks, but Scott has not given me any reason to believe that he's aware
prodRow["Total"] is of the type System.String, not System.Decimal.

Well, I did suspect that the type being returned was the issue (which is why
I mentioned that it was coming from a loosely-typed dataset).
He did, after all, try to explain that it returns System.Object and then
tried to cast it to System.Decimal, claiming that it didn't work.

I said that the formatting didn't work, not the cast.
That's an indication, IMO, that he doesn't realize System.String can't be
explicitly cast to System.Decimal or that he doesn't realize
prodRow["Total"] is not returning System.Decimal, but probably
System.String.

Actually, because the cast DID work (meaning, no exception and data
returned), I assumed that I was NOT getting back a String. And this is why
I was attempting to cast my return value, when what I should have been doing
was converting my return value.
 
D

Dave Sexton

Hi Scott,
lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

I suspect that will throw an InvalidCastException because prodRow["Total"]
is returning System.String, not System.Decimal.

No, it doesn't throw an exception, it just produces my (correct) data, but
without the currency formatting.

If you're not getting an InvalidCastException that means the expression must
be returning System.Decimal.

But the following worked just fine for me:

string money = string.Format("{0:c}", 10M);
Console.WriteLine(money);

Output:

$10.00

It sounds to me like you're either executing the code under a Culture that is
preventing the expected currency format from being produced or you found a bug
in the framework; although, with such a simple line of code a bug is hard for
me to believe.
Yes, the following should work:

lblTotal.Text = Convert.ToDecimal(prodRow["Total"]).ToString("C");

No, that doesn't work for me. And, this is something I mentioned in my OP.
When I try to pass the "C" argument to the ToString method, I get a build
error indicating that there is no ToString method that takes 1 argument.

If it doesn't work for you then you're not doing it correctly.

Look closely. I'm not calling ToString on prodRow["Total"] I'm calling
ToString on the result of Convert.ToDecimal, which returns System.Decimal.
System.Decimal has a ToString overload that accepts a format string:

object o = 10M;

string money = Convert.ToDecimal(o).ToString("C");
Console.WriteLine(money);

Output:

$10.00

<snip>

--
Dave Sexton

Scott M. said:
lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

I suspect that will throw an InvalidCastException because prodRow["Total"]
is returning System.String, not System.Decimal.

No, it doesn't throw an exception, it just produces my (correct) data, but
without the currency formatting.

In the end, I should have been using the Convert class, which solved my
problem.

Yes, the following should work:

lblTotal.Text = Convert.ToDecimal(prodRow["Total"]).ToString("C");

No, that doesn't work for me. And, this is something I mentioned in my OP.
When I try to pass the "C" argument to the ToString method, I get a build
error indicating that there is no ToString method that takes 1 argument.

What did work for me was this:

lblTotal.Text = String.Format("{0:c}",Convert.ToDecimal(prodRow["Total"]));
FYI, you might prefer to use a strong-typed DataSet so that the following
code could be used instead:

Yes, I am aware of the benefits of strongly-typed datasets, but in this case
it is not an option.

Thanks.
 
D

Dave Sexton

Hi Scott,
Thanks, but Scott has not given me any reason to believe that he's aware
prodRow["Total"] is of the type System.String, not System.Decimal.

Well, I did suspect that the type being returned was the issue (which is why
I mentioned that it was coming from a loosely-typed dataset).

The fact that you're not using a strong-typed DataSet doesn't have anything to
do with this issue. What matters is the Type being returned from
prodRow["Total"], which you recently verified to be System.Decimal (otherwise
that explicit cast would have thrown an InvalidCastException).
I said that the formatting didn't work, not the cast.

True. I assumed that the cast wouldn't work otherwise {0:c} should've worked
just fine. I'm still not sure why it doesn't.
That's an indication, IMO, that he doesn't realize System.String can't be
explicitly cast to System.Decimal or that he doesn't realize
prodRow["Total"] is not returning System.Decimal, but probably
System.String.

Actually, because the cast DID work (meaning, no exception and data
returned), I assumed that I was NOT getting back a String. And this is why
I was attempting to cast my return value, when what I should have been doing
was converting my return value.

You might want to try and understand why the following isn't working if
prodRow["Total"] is returning System.Decimal:

string.Format("{0:c}", prodRow["Total"]);

No cast should be required, unless prodRow["Total"] is actually returning
System.String, of course ;)

(See my examples in my last, related response)
 
S

Scott M.

The fact that you're not using a strong-typed DataSet doesn't have
anything to do with this issue.

Well, sure it does. Extracting a DataRow.Item from a loosely-typed DataSet
that never had any of its DataColumns data types established returns a
System.Object, not a decimal as you suspect. Because the data was NOT
coming out of the DataSet as a numeric type, I had to convert it to a
numeric type before String.Format would work. My initial attempts were to
cast (not convert) the System.Object being returned.

If you are using a Strongly-Typed DataSet, then extracting a DataRow.Item
will result in whatever type that DataColumn is mapped to (and so, no
conversion would have been necessary to format the decimal as currency).
What matters is the Type being returned from prodRow["Total"], which you
recently verified to be System.Decimal (otherwise that explicit cast would
have thrown an InvalidCastException).

No. As I have said, I get back a System.Object (not System.Decimal), which
is what you always get back from loosely-typed DataSets and because the
actual data can be cast as a decimal, my attempts to do so were successful,
but I had not "converted" the data to a decmial, I had only "cast" is as a
decimal.
True. I assumed that the cast wouldn't work otherwise {0:c} should've
worked just fine. I'm still not sure why it doesn't.

As was clarified for me in another post, casting and converting aren't the
same thing.
That's an indication, IMO, that he doesn't realize System.String can't
be explicitly cast to System.Decimal or that he doesn't realize
prodRow["Total"] is not returning System.Decimal, but probably
System.String.

Actually, because the cast DID work (meaning, no exception and data
returned), I assumed that I was NOT getting back a String. And this is
why I was attempting to cast my return value, when what I should have
been doing was converting my return value.

You might want to try and understand why the following isn't working if
prodRow["Total"] is returning System.Decimal:

string.Format("{0:c}", prodRow["Total"]);

I never said it was returning System.Decimal, you did. I have been telling
you that it returns System.Object.
No cast should be required, unless prodRow["Total"] is actually returning
System.String, of course ;)

As I said, no cast is required at all, it is a convert that is required.
 
S

Scott M.

Look closely. I'm not calling ToString on prodRow["Total"] I'm calling
ToString on the result of Convert.ToDecimal, which returns System.Decimal.
System.Decimal has a ToString overload that accepts a format string:

object o = 10M;

string money = Convert.ToDecimal(o).ToString("C");
Console.WriteLine(money);

Output:

$10.00

Yes Dave, I see the difference in the ToString call now. Thanks!
 
D

Dave Sexton

Hi Scott,

All classes, structures, delegates and enums derive from System.Object through
inheritance. It's quite possible that the System.Object being returned from
your "loosely-typed" DataRow is actually a boxed System.Decimal.

If you try to cast System.Object into System.Decimal you will get an
InvalidCastException unless the "object" is actually a boxed "decimal" type.

In other words, the following throws an InvalidCastException at runtime:

object o = "9.99";
decimal d = (decimal) o;

You cannot cast an object into decimal unless the object IS a decimal.
However, it may be "converted", as you've discovered.

Therefore, if the following doesn't thrown an InvalidCastException:
lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

That means prodRow["Total"] MUST be returning System.Decimal. It does not
matter whether the DataSet is "loosely-typed" or "strongly-typed".

Since we know that prodRow["Total"] is returning System.Decimal
(System.Decimal derives from System.Object, just like every other "entity" in
the framework), then the following should work perfectly:

lblTotal.Text = String.Format("{0:c}", prodRow["Total"]);

If it doesn't work then one of the following must be true:

A. prodRow["Total"] is actually returning System.String (which also derives
from System.Object, just like every other "entity" in the framework)
Although, it really could be returning any non-numeric data but I suspected
throughout this conversation that it's probably returning System.String.

B. You have set the current Culture to something other than what you expect
and it has changed the meaning of the "currency" format

C. You have identified a bug in the framework (doubtful)


I really can't see any other way for your evidence to hold true.


--
Dave Sexton

Scott M. said:
The fact that you're not using a strong-typed DataSet doesn't have anything
to do with this issue.

Well, sure it does. Extracting a DataRow.Item from a loosely-typed DataSet
that never had any of its DataColumns data types established returns a
System.Object, not a decimal as you suspect. Because the data was NOT
coming out of the DataSet as a numeric type, I had to convert it to a
numeric type before String.Format would work. My initial attempts were to
cast (not convert) the System.Object being returned.

If you are using a Strongly-Typed DataSet, then extracting a DataRow.Item
will result in whatever type that DataColumn is mapped to (and so, no
conversion would have been necessary to format the decimal as currency).
What matters is the Type being returned from prodRow["Total"], which you
recently verified to be System.Decimal (otherwise that explicit cast would
have thrown an InvalidCastException).

No. As I have said, I get back a System.Object (not System.Decimal), which
is what you always get back from loosely-typed DataSets and because the
actual data can be cast as a decimal, my attempts to do so were successful,
but I had not "converted" the data to a decmial, I had only "cast" is as a
decimal.
True. I assumed that the cast wouldn't work otherwise {0:c} should've
worked just fine. I'm still not sure why it doesn't.

As was clarified for me in another post, casting and converting aren't the
same thing.
That's an indication, IMO, that he doesn't realize System.String can't be
explicitly cast to System.Decimal or that he doesn't realize
prodRow["Total"] is not returning System.Decimal, but probably
System.String.

Actually, because the cast DID work (meaning, no exception and data
returned), I assumed that I was NOT getting back a String. And this is
why I was attempting to cast my return value, when what I should have been
doing was converting my return value.

You might want to try and understand why the following isn't working if
prodRow["Total"] is returning System.Decimal:

string.Format("{0:c}", prodRow["Total"]);

I never said it was returning System.Decimal, you did. I have been telling
you that it returns System.Object.
No cast should be required, unless prodRow["Total"] is actually returning
System.String, of course ;)

As I said, no cast is required at all, it is a convert that is required.
(See my examples in my last, related response)
 
S

Scott M.

I understand Dave, but I did a test to see exactly what I was getting back
(using GetType()) and found that accessing my loosely-typed data was not
returning a decimal, but a string. Yet, the cast to a decimal does not
throw an exception. I have not made any changes to any culture settings.


Dave Sexton said:
Hi Scott,

All classes, structures, delegates and enums derive from System.Object
through inheritance. It's quite possible that the System.Object being
returned from your "loosely-typed" DataRow is actually a boxed
System.Decimal.

If you try to cast System.Object into System.Decimal you will get an
InvalidCastException unless the "object" is actually a boxed "decimal"
type.

In other words, the following throws an InvalidCastException at runtime:

object o = "9.99";
decimal d = (decimal) o;

You cannot cast an object into decimal unless the object IS a decimal.
However, it may be "converted", as you've discovered.

Therefore, if the following doesn't thrown an InvalidCastException:
lblTotal.Text = String.Format("{0:c}", (decimal) prodRow["Total"]);

That means prodRow["Total"] MUST be returning System.Decimal. It does not
matter whether the DataSet is "loosely-typed" or "strongly-typed".

Since we know that prodRow["Total"] is returning System.Decimal
(System.Decimal derives from System.Object, just like every other "entity"
in the framework), then the following should work perfectly:

lblTotal.Text = String.Format("{0:c}", prodRow["Total"]);

If it doesn't work then one of the following must be true:

A. prodRow["Total"] is actually returning System.String (which also
derives from System.Object, just like every other "entity" in the
framework)
Although, it really could be returning any non-numeric data but I
suspected throughout this conversation that it's probably returning
System.String.

B. You have set the current Culture to something other than what you
expect and it has changed the meaning of the "currency" format

C. You have identified a bug in the framework (doubtful)


I really can't see any other way for your evidence to hold true.


--
Dave Sexton

Scott M. said:
The fact that you're not using a strong-typed DataSet doesn't have
anything to do with this issue.

Well, sure it does. Extracting a DataRow.Item from a loosely-typed
DataSet that never had any of its DataColumns data types established
returns a System.Object, not a decimal as you suspect. Because the data
was NOT coming out of the DataSet as a numeric type, I had to convert it
to a numeric type before String.Format would work. My initial attempts
were to cast (not convert) the System.Object being returned.

If you are using a Strongly-Typed DataSet, then extracting a DataRow.Item
will result in whatever type that DataColumn is mapped to (and so, no
conversion would have been necessary to format the decimal as currency).
What matters is the Type being returned from prodRow["Total"], which you
recently verified to be System.Decimal (otherwise that explicit cast
would have thrown an InvalidCastException).

No. As I have said, I get back a System.Object (not System.Decimal),
which is what you always get back from loosely-typed DataSets and because
the actual data can be cast as a decimal, my attempts to do so were
successful, but I had not "converted" the data to a decmial, I had only
"cast" is as a decimal.
He did, after all, try to explain that it returns System.Object and
then tried to cast it to System.Decimal, claiming that it didn't work.

I said that the formatting didn't work, not the cast.

True. I assumed that the cast wouldn't work otherwise {0:c} should've
worked just fine. I'm still not sure why it doesn't.

As was clarified for me in another post, casting and converting aren't
the same thing.
That's an indication, IMO, that he doesn't realize System.String can't
be explicitly cast to System.Decimal or that he doesn't realize
prodRow["Total"] is not returning System.Decimal, but probably
System.String.

Actually, because the cast DID work (meaning, no exception and data
returned), I assumed that I was NOT getting back a String. And this is
why I was attempting to cast my return value, when what I should have
been doing was converting my return value.

You might want to try and understand why the following isn't working if
prodRow["Total"] is returning System.Decimal:

string.Format("{0:c}", prodRow["Total"]);

I never said it was returning System.Decimal, you did. I have been
telling you that it returns System.Object.
No cast should be required, unless prodRow["Total"] is actually
returning System.String, of course ;)

As I said, no cast is required at all, it is a convert that is required.
(See my examples in my last, related response)
 

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

Top