5

I'm trying to make a List<byte> from a file that contains string (Hexadecimal) . the definition is :

List<byte> myArray = new List<byte>();

if I want to add my information directly I use something like this :

  myArray.Add(0xb8);

Note : Without any quotation or double-quotation .

The problem is when I want to do the same thing from file! Now I want to know what 0xb8's type is so I use the following code :

0xc3.GetType().ToString()

the result is : System.Int32 !!!!

but when I read strings from a file and use code like this , it give me the following error .

code :

 Line = "0xb8";
myArray.Add(Convert.ToInt32(Line));

Error :

Argument 1: cannot convert from 'int' to 'byte'

and it's clear . because the only overload of myArray gets only a byteas argumant. What makes thing so complicated for me is why it doesn't give me any error when I add a Int32 to myArray in myArray.Add(0xb8); .

I think it should be a form of byte ! maybe !

Why doesn't it give any errors and how can accomplish this scenario (I mean add byte from string to myArray ) ?

JackWhiteIII
  • 1,388
  • 2
  • 11
  • 25
Mohammad Sina Karvandi
  • 1,064
  • 3
  • 25
  • 44

4 Answers4

5

This works:

var list = new List<byte>();

byte byteValue = 0xb8;
list.Add(byteValue);

This doesn't ("cannot convert from 'int' to 'byte'"):

var list = new List<byte>();

int byteValue = 0xb8;
list.Add(byteValue);

Yet in both cases 0xb8 is recognized as System.Int32. So why does the compiler allow implicit conversion of an int to byte in the first example?

See C# spec 6.1.9 Implicit constant expression conversions:

A constant-expression (§7.19 [including literals]) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant-expression is within the range of the destination type.

This exists because all integer literals are either (u)int or (u)long, as specified in 2.4.4.2 Integer literals.

Given 0 <= 0xb8 <= 255, the compiler allows the implicit conversion.

In your case, because of reasons explained by @usr, you'll need to do an explicit conversion:

myArray.Add((byte)Convert.ToInt32(Line, 16));
Community
  • 1
  • 1
CodeCaster
  • 147,647
  • 23
  • 218
  • 272
4

0xb8 is an integer literal (like 1234). "0xb8" is a string literal (like "x"). There is no such thing as a hex literal in C#. It's an int literal in hex format. So that explains the trouble you had with the literals.

Not all of the string parsing functions support hex input. See this for how to parse a hex string.

When a parsing function gives you an int and you need to treat it as a byte, you can cast: (byte)myInt. This is safe because the parsed value is guaranteed to fit into a byte.

In some places the compiler is able to convert automatically for you if you have been using a constant such as 0xb8. Since you will not have that in practice (you are parsing a file) that case is not relevant for the final code. But this explains why that works.

Community
  • 1
  • 1
usr
  • 168,620
  • 35
  • 240
  • 369
  • 1
    his problem is that there is some intelligence in the compiler so that integral literals are converted to the right type by the compiler... – xanatos Jun 16 '15 at 10:46
  • @xanatos right. *Many* things to explain here! What a surprisingly confusing problem for a beginner. – usr Jun 16 '15 at 10:48
2

How can accomplish this scenario (I mean add byte from string to myArray ) ?

List<byte> myArray = new List<byte>();
string Line = "0xb8";
myArray.Add(Convert.ToByte(Line, 16));

why it doesn't give me any error when I add a Int32 to myArray in myArray.Add(0xb8);

compiler can see that 0xb8 is in Byte values range

myArray.Add(0xb8);  // ok
myArray.Add(0xff);  // ok
myArray.Add(0x100); // cannot convert from int to byte
ASh
  • 34,632
  • 9
  • 60
  • 82
2

You can get rid of that compiler error by just casting the value to byte:

myArray.Add((byte)Convert.ToInt32(Line));

However, when you run that code you will get a different error:

Unhandled Exception: System.FormatException: Input string was not in a correct format.

That's because the Convert.ToInt32 method doesn't parse hexadecimal numbers out of the box.

You can specify the base when you convert the string to a number:

myArray.Add((byte)Convert.ToInt32(Line, 16));
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • Or you can save yourself the cast and use `Convert.ToByte(Line, 16)` instead...then if you happen to provide a `Line` of "0xF8C4" you can catch an `OverflowException` instead of just quietly truncating to 0xC4 – Sabre Jun 16 '15 at 14:46