Convert.ChangeType matrix - c#

Is there any resource that shows .NET Convert.ChangeType() results in a table? i.e. converting from which type to which type will be successful, overflow, invalid cast or throwing other exceptions.
In particular, I want to know whether converting between signed and unsigned numerals of the same size (e.g. Int32 and UInt32) will be successful, overflow or invalid cast.

int32 max value is 2,147,483,647 and UInt32 max value is 4,294,967,295 so if you converted a number to uint32 from int32 and stuck to int32 max boundary and vise versa there will be no issue, otherwise it will give you an exception division by zero i guess

Related

C#: Why is 0xFFFFFFFF a uint when it represents -1?

I don't understand why C# considers the literal 0xFFFFFFFF as a uint when it also represents -1 for int types.
The following is code was entered into the Immediate Window shown here with the output:
int i = -1;
-1
string s = i.ToString("x");
"ffffffff"
int j = Convert.ToInt32(s, 16);
-1
int k = 0xFFFFFFFF;
Cannot implicitly convert type 'uint' to 'int'. An explicit conversion exists (are you missing a cast?)
int l = Convert.ToInt32(0xFFFFFFFF);
OverflowException was unhandled: Value was either too large or too small for an Int32.
Why can the string hex number be converted without problems but the literal only be converted using unchecked?
Why is 0xFFFFFFFF a uint when it represents -1?
Because you're not writing the bit pattern when you write
i = 0xFFFFFFFF;
you're writing a number by C#'s rules for integer literals. With C#'s integer literals, to write a negative number we write a - followed by the magnitude of the number (e.g., -1), not the bit pattern for what we want. It's really good that we aren't expected to write the bit pattern, it would make it really awkward to write negative numbers. When I want -3, I don't want to have to write 0xFFFFFFFD. :-) And I really don't want to have to vary the number of leading Fs based on the size of the type (0xFFFFFFFFFFFFFFFD for a long -3).
The rule for choosing the type of the literal is covered by the above link by saying:
If the literal has no suffix, it has the first of these types in which its value can be represented: int, uint, long, ulong.
0xFFFFFFFF doesn't fit in an int, which has a maximum positive value of 0x7FFFFFFF, so the next in the list is uint, which it does fit in.
0xffffffff is 4294967295 is an UInt32 that just happens to have a bit pattern equal to the Int32 -1 due to the way negative numbers are represented on computers. Just because they have the same bit pattern, that doesn't mean 4294967295 = -1. They're completely different numbers so of course you can't just trivially convert between the two. You can force the reintepretation of the bit pattern by using an explicit cast to int: (int)0xffffffff.
The C# docs say that the compiler will try to fit the number you provide in the smallest type that can fit it. That doc is a bit old, but it applies still. It always assumes that the number is positive.
As a fallback you can always coerce the type.
The C# language rules state that 0xFFFFFFFF is an unsigned literal.
A C# signed int is 2's complement type. That scheme uses 0xFFFFFFFF to represent -1. (2's complement is a clever scheme since it doesn't have a signed zero).
For an unsigned int, 0xFFFFFFFF is the largest value it can take, and due to its size, it can't be converted to a signed int.

0x80000000 == 2147483648 in C# but not in VB.NET

In C#:
0x80000000==2147483648 //outputs True
In VB.NET:
&H80000000=2147483648 'outputs False
How is this possible?
This is related to the history behind the languages.
C# always supported unsigned integers. The value you use are too large for int so the compiler picks the next type that can correctly represent the value. Which is uint for both.
VB.NET didn't acquire unsigned integer support until version 8 (.NET 2.0). So traditionally, the compiler was forced to pick Long as the type for the 2147483648 literal. The rule was however different for the hexadecimal literal, it traditionally supported specifying the bit pattern of a negative value (see section 2.4.2 in the language spec). So &H80000000 is a literal of type Integer with the value -2147483648 and 2147483648 is a Long. Thus the mismatch.
If you think VB.NET is a quirky language then I'd invite you to read this post :)
The VB version should be:
&H80000000L=2147483648
Without the 'long' specifier ('L'), VB will try to interpret &H8000000 as an integer. If you force it to consider this as a long type, then you'll get the same result.
&H80000000UI will also work - actually this is the type (UInt32) that C# regards the literal as.
This happens because the type of the hexadecimal number is UInt32 in C# and Int32 in VB.NET.
The binary representation of the hexadecimal number is:
10000000000000000000000000000000
Both UInt32 and Int32 take 32 bits, but because Int32 is signed, the first bit is considered a sign to indicate whether the number is negative or not: 0 for positive, 1 for negative. To convert a negative binary number to decimal, do this:
Invert the bits. You get 01111111111111111111111111111111.
Convert this to decimal. You get 2147483647.
Add 1 to this number. You get 2147483648.
Make this negative. You get -2147483648, which is equal to &H80000000 in VB.NET.

Value was either too large or too small for an Int32 in asp.net

I have a singup forum, in which there is aphone number field
code is:
try
{
cz.SignUp(nametxt.Value, passtxt.Value,
Convert.ToInt32(DropDownList1.SelectedValue),
Convert.ToInt32(DropDownList2.SelectedValue),
Convert.ToInt32(DropDownList3.SelectedValue),
mailtxt.Value,Convert.ToInt32(numbtxt.Value));
//GridView1.DataSource=ca.viewadmin();
Lbe6.Text = ("Signup Success");
}
catch
{
lbe5.Text = ("FAILED");
}
But when I click on submit the button it shows me an error.
Value was either too large or too small for an Int32.
I also tried uint and int64 but it did not work
Phone numbers are not numbers.
You should use a string.
Remember: If you can't add it, it isn't a number.
Phone numbers are not NUMBERS
It is better to take string for storing the Phone Numbers.
On a side note:-
From MSDN:
Integer variables are stored as signed 32-bit (4-byte) integers
ranging in value from -2,147,483,648 through 2,147,483,647.
And INT32
Int32 is an immutable value type that represents signed integers with
values that range from negative 2,147,483,648 (which is represented by
the Int32.MinValue constant) through positive 2,147,483,647 (which is
represented by the Int32.MaxValue constant. The .NET Framework also
includes an unsigned 32-bit integer value type, UInt32, which
represents values that range from 0 to 4,294,967,295.

String to Int conversion: Convert.toInt16

This is the code.
CODE 1: cmd.Parameters.Add("#RateCenterID", OleDbType.Integer).Value = Convert.ToInt32(ratecenterid.Text);
CODE 2: cmd.Parameters.Add("#QuantityThreshold", OleDbType.Integer).Value = Convert.ToIn32(quantityThreshold.Text);
I get the following error in the CODE 2 but not in CODE 1
Error: Value was either too large or too small for an Int32.
kindly help me
Regards,
Arjun
Try entering a smaller or larger value in the quantityThreshold text box.
Update
Okay, reading your comment response to Saeed Amiri, 4036953909 is too large for an int - it's range is -2147483648 to 2147483647
You could use a uint which has a range 0 to 4294967295
Convert.ToUInt32(ratecenterid.Text)
Although you will likely need to change the parameter type to OleDbType.UnsignedInt as well.
From MSDN - Int32 Structure:
Int32 is an immutable value type that represents signed integers with values that range from negative 2,147,483,648 (which is represented by the Int32.MinValue constant) through positive 2,147,483,647 (which is represented by the Int32.MaxValue constant. The .NET Framework also includes an unsigned 32-bit integer value type, UInt32, which represents values that range from 0 to 4,294,967,295.
You are trying to use a value that is not possible to represent as an Int32.
Not sure why your title is about Int16 as your code and error indicate you are using Int32 - regardless - Int16 has an much smaller range than Int32:
The Int16 value type represents signed integers with values ranging from negative 32768 through positive 32767.
You need to either use UInt32 or long.
sample value for "QuantityThreshold = 4036953909"
Right. That wouldn't fit into an Int16 (as per your title), which has a maximum value of 32767. That wouldn't even fit into an Int32 (as per your code) (max value 2,147,483,647). It would fit into a UInt32, and would easily fit into an Int64 - perhaps the latter is what you're really looking for?
(You should also clarify your qusetion - are you using Int32 or Int16?)
Your current value is within UInt32 scope, and OleDbType.Integer size is 4 byte and is mapped to Int32, if you want use UInt32 you should use UnsignedInt as your parameter type, and use UInt32 conversion:
cmd.Parameters.Add("#QuantityThreshold", OleDbType.UnsignedInt).Value =
Convert.ToUIn32(quantityThreshold.Text)
Int32 has a range of -2147483648 to 2147483647. You could use a larger type e.g., uint (0 to 4294967295) or long (-9.2233E+18 to 9.2233E+18).
Ref: Error: Value was either too large or too small for an Int32
That number is way to big for an int32. You should just store it as a
string.(varchar)
You got the why in the other answers but I didn't see anyone mentioning ToInt64. Simply change the ToInt32 to ToInt64 and also make sure that the datatype of #QuantityThreshold can handle it.
The Int64 value type represents integers with values ranging from negative 9,223,372,036,854,775,808 through positive 9,223,372,036,854,775,807.
To fix your problem you will have to put the validation on your textbox - quantityThreshold, it should have the value with in the range of Int32. or use a larger type.

.NET primitives and type hierarchies, why was it designed like this?

I would like to understand why on .NET there are nine integer types: Char, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, and UInt64; plus other numeric types: Single, Double, Decimal; and all these types have no relation at all.
When I first started coding in C# I thought "cool, there's a uint type, I'm going to use that when negative values are not allowed". Then I realized no API used uint but int instead, and that uint is not derived from int, so a conversion was needed.
What are the real world application of these types? Why not have, instead, integer and positiveInteger ? These are types I can understand. A person's age in years is a positiveInteger, and since positiveInteger is a subset of integer there's so need for conversion whenever integer is expected.
The following is a diagram of the type hierarchy in XPath 2.0 and XQuery 1.0. If you look under xs:anyAtomicType you can see the numeric hierarchy decimal > integer > long > int > short > byte. Why wasn't .NET designed like this? Will the new framework "Oslo" be any different?
My guess would be because the underlying hardware breaks that class hierarchy. There are (perhaps surprisingly) many times when you care that a UInt32 is a 4 bytes big and unsigned, so a UInt32 is not a kind of Int32, nor is an Int32 a type of Int64.
And you almost always care about the difference between an int and a float.
Fundamentally, inheritance & the class hierarchy are not the same as mathematical set inclusion. The fact that the values a UInt32 can hold are a strict subset of the values an Int64 can hold does not mean that a UInt32 is a type of Int64. Less obviously, an Int32 is not a type of Int64 - even though there's no conceptual difference between them, their underlying representations are different (4 bytes versus 8 bytes). Decimals are even more different.
XPath is different: the representations for all the numeric types are fundamentally the same - a string of ASCII digits. There, the difference between a short and a long is one of possible range rather than representation - "123" is both a valid representation of a short and a valid representation of a long with the same value.
Decimal is intended for calculations that need precision (basically, money).
See here: http://msdn.microsoft.com/en-us/library/364x0z75(VS.80).aspx
Singles/Doubles are different to decimals, because they're intended to be an approximation (basically, for scientific calculations).
That's why they're not related.
As for bytes and chars, they're totally different: a byte is 0-255, whereas a char is a character, and can hence store unicode characters (there are a lot more than 255 of them!)
Uints and ints don't convert automatically, because they can each store values that are impossible for the other (uints have twice the positive range of ints).
Once you get the hang of it all, it actually does make a lot of sense.
As for your ages thing, i'd simply use an int ;)

Categories

Resources