What is the equivalent of "(byte)" in VB.NET? - c#

What is the equivalent of (byte) in VB.NET:
C#:
uint value = 1161;
byte data = (byte)value;
data = 137
VB.NET:
Dim value As UInteger = 1161
Dim data1 As Byte = CType(value, Byte)
Dim data2 As Byte = CByte(value)
Exception: Arithmetic operation resulted in an overflow.
How can I achieve the same result as in C#?

By default, C# does not check for integer overflows, but VB.NET does.
You get the same exception in C# if you e.g. wrap your code in a checked block:
checked
{
uint value = 1161;
byte data = (byte)value;
}
In your VB.NET project properties, enable Configuration Properties => Optimizations => Remove Integer Overflow Checks, and your VB.NET code will work exactly like your C# code.
Integer overflow checks are then disabled for your entire project, but that's usually not a problem.

Try first chopping the most significant bytes off the number, then converting it to Byte:
Dim value As UInteger = 1161
Dim data1 As Byte = CType(value And 255, Byte)
Dim data2 As Byte = CByte(value And 255)

To get just the most significant byte, you can do the rather hackalicious
Dim data1 = BitConvertor.GetBytes(value)(0)
It's explicit, and you wouldn't need to disable overflow checking.

Related

Why integer arithmetic result showing different values in VB.NET and C#?

I have converted C# decrypt/encrypt functions to VB.NET. When I test the result in C# is showing below result but in VB.NET it throws an exception. Could you explain to me how C# showing the below result?
Below codes are tested in VS 2010 with 4.0 framework.
C# Code
class Program
{
static void Main(string[] args)
{
byte bytTen = 10;
int aa = 1527870874;
int bb = 28904;
int cc = 35756;
Console.WriteLine((bytTen + aa) * bb + cc);
Console.ReadKey();
}
}
Result: 726329420
VB.NET Code
Module Module1
Sub Main()
Dim bytTen As Byte = 10
Dim aa As Integer = 1527870874, bb As Integer = 28904, cc As Integer = 35756
Console.WriteLine((bytTen + aa) * bb + cc)
Console.ReadKey()
End Sub
End Module
Result: Arithmetic operation resulted in an overflow.
The C# code is running as unchecked code (where integer overflow is ignored).
The VB code is running in as checked, where the runtime detects an integer overflow and throws an exception.
To get the same result in VB, you need to check the project-level option "Remove integer overflow checks" on the "Advanced Compiler Settings" options via the "Compile" tab of the project options.
C# by default removes integer overflow checks (but this can also be changed on the C# project options), while VB by default has integer overflow checks.

C# byte array conversion to VB.NET

As per my last question I'm borrowing some code from the Opus project to integrate into VB.NET software.
Consider
byte[] buff = _encoder.Encode(segment, segment.Length, out len);
which I've translated to:
Dim buff(wavEnc.Encode(segment, segment.Length, len)) As Byte
It is throwing a:
Value of type '1-dimensional array of Byte' cannot be converted to 'Integer' error...
How can I fix this problem?
Try this:
Dim buff = wavEnc.Encode(segment, segment.Length, len)
Of course you can do a direct translation of the c#:
Dim buff As Byte() = wavEnc.Encode(segment, segment.Length, len)
No need for a type at all - let the compiler figure it out.
_encoder.Encode() is the right-hand side of an assignment. The left-hand side is a byte array.
The way you are using it in your VB sample is as an array dimensioner: an Integer.

Converting byte array to string with correct encoding

I have this bit of C# code that I have translated to VB using http://www.developerfusion.com/tools/convert/csharp-to-vb/
private string DecodeToken (string token, string key)
{
byte [] buffer = new byte[0];
string decoded = "";
int i;
if (Scramble (Convert.FromBase64String(token), key, ref buffer))
{
for (i=0;i<buffer.Length;i++)
{
decoded += Convert.ToString((char)buffer[i]);
}
}
return(decoded);
}
Which, after a little modification, gives this:
Private Function DecodeToken(token As String, key As String) As String
Dim buffer As Byte()
Dim decoded As String = ""
Dim index As Integer
If Scramble(Convert.FromBase64String(token), key, buffer) Then
For index = 0 To buffer.Length - 1
decoded += Convert.ToString(ChrW(buffer(index)))
Next
'decoded = UTF8Encoding.ASCII.GetString(pbyBuffer)
'decoded = UnicodeEncoding.ASCII.GetString(pbyBuffer)
'decoded = ASCIIEncoding.ASCII.GetString(pbyBuffer)
End If
Return decoded
End Function
Scramble just rearranges the array in a specific way and I've checked the VB and C# outputs against each other so it can be ignored. It's inputs and outputs are byte arrays so it shouldn't affect the encoding.
The problem lies in that the result of this function is fed into a hashing algorithm which is then compared against the hashing signature. The result of the VB version, when hashed, does not match to the signature.
You can see from the comments that I've attempted to use different encodings to get the byte buffer out as a string but none of these have worked.
The problem appears to lie in the transalation of decoded += Convert.ToString((char)buffer[i]); to decoded += Convert.ToString(ChrW(buffer(index))).
Does ChrW produce the same result as casting as a char and which encoding will correctly duplicate the reading of the byte array?
Edit: I always have Option Strict On but it's possible that the original C# doesn't so it may be affected by implicit conversion. What does the compiler do in that situation?
Quick answer
decoded += Convert.ToString((char)buffer[i]);
is equivalent to
decoded &= Convert.ToString(Chr(buffer[i]));
VB.Net stops you taking the hacky approach used in the c# code, a Char is Unicode so consists of two bytes.
This looks likes a better implementation of what you have.
Private Function DecodeToken(encodedToken As String, key As String) As String
Dim scrambled = Convert.FromBase64String(encodedToken)
Dim buffer As Byte()
Dim index As Integer
If Not Scramble(scrambled, key, buffer) Then
Return Nothing
End If
Dim descrambled = new StringBuilder(buffer.Length);
For index = 0 To buffer.Length - 1
descrambled.Append(Chr(buffer(index)))
Next
Return descrambled.ToString()
End Function
have you tried the most direct code translation:
decoded += Convert.ToString(CType(buffer[i], char))
When covnerting a byte array to a string you should really make sure you know the encoding first though. If this is set in whatever is providing the byte array then you should use that to decode the string.
For more details on the ChrW (and Chr) functions look at http://msdn.microsoft.com/en-us/library/613dxh46%28v=vs.80%29.aspx . In essence ChrW assumes that the passed int is a unicode codepoint which may not be a valid assumption (I believe from 0 to 127 this wouldn't matter but the upper half of the byte might be different). if this is the problem then it will likely be accented and other such "special" characters that are causing the problem.
Give the following a go:
decoded += Convert.ToChar(foo)
It will work (unlike my last attempt that made assumptions about implicit conversions being framework specific and not language specific) but I can't guarantee that it will be the same as the .NET.
Given you say in comments you expected to use Encoding.xxx.GetString then why don't you use that? Do you know what the encoding was in the original string to byte array? If so then just use that. It is the correct way to convert a byte array to a string anyway since doing it byte by byte will definitely break for any multi-byte characters (clearly).
A small improvement
Private Function DecodeToken(encodedToken As String, key As String) As String
Dim scrambled = Convert.FromBase64String(encodedToken)
Dim buffer As Byte()
Dim index As Integer
If Not Scramble(scrambled, key, buffer) Then
Return Nothing
End If
Dim descrambled = System.Text.Encoding.Unicode.GetString(buffer, 0, buffer.Length);
Return descrambled
End Function

Convert C# function to VB, char value overflow error

I need the following function converted to VB.NET, but I'm not sure how to handle the statement
res = (uint)((h * 0x21) + c);
Complete function:
private static uint convert(string input)
{
uint res = 0;
foreach (int c in input)
res = (uint)((res * 0x21) + c);
return res;
}
I created the following, but I get an overflow error:
Private Shared Function convert(ByVal input As String) As UInteger
Dim res As UInteger = 0
For Each c In input
res = CUInt((res * &H21) + Asc(c)) ' also tried AscW
Next
Return res
End Function
What am I missing? Can someone explain the details?
Your code is correct. The calculation is overflowing after just a few characters since res increases exponentially with each iteration (and it’s not the conversion on the character that’s causing the overflow, it’s the unsigned integer that overflows).
C# by default allows integer operations to overflow – VB doesn’t. You can disable the overflow check in the project settings of VB, though. However I would try not to rely on this. Is there a reason this particular C# has to be ported? After all, you can effortlessly mix C# and VB libraries.
Here is a useful online converter: http://www.developerfusion.com/tools/convert/csharp-to-vb/

"Use of unassigned local variable" when trying to pass a struct by reference

I have a VB class library I built from an existing VB class which wraps an unmanaged DLL. The VB class library contains the DLL functions and various structs and types associated with the DLL functions.
I am using the class lib in a C# project and one of the functions in the class lib requires me to pass a struct as an argument. This is where I am running into trouble.
Here is the VB code for the DLL:
Declare Auto Function CtSetVRegister Lib "Ctccom32v2.dll" _
(ByVal ConnectID As Integer, ByRef Storage As CT_VARIANT) As Integer
Here is the VB struct:
<StructLayout(LayoutKind.Sequential, Pack:=1)> _
Public Structure CT_VARIANT
Dim vRegister As Integer 'Variant Register desired
Dim type As Integer 'Format want results returned in
Dim precision As Integer 'Precision desired for floating point conversions
Dim flags As Integer 'Specially defined flags, 0 for normal, (indirection, etc.)
Dim cmd As Integer 'Special commands, 0 for normal operation
Dim taskHandle As Integer 'Alternate task handle for local task register access, 0 = default public
Dim slength As Integer 'Length of bytes returned in stringVar, not include null
Dim indexCol As Integer 'Column (X) selection, base 0
Dim indexRow As Integer 'Row (X) selection base 0
Dim IntegerIntVar As Integer '32 bit signed integer storage
Dim FloatVar As Single '32 bit float
Dim DoubleVar As Double '64 bit double in Microsoft format
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=223)> _
Public stringVar() As Byte 'null terminated ASCII string of bytes (1 to 224)
End Structure
The C# method I am writing requires me to set the necessary values in the struct and then pass those to the DLL function:
private void btnWriteVReg_Click(object sender, System.EventArgs e)
{
int results;
CTC_Lib.Ctccom32v2.CT_VARIANT Var;
Var.vRegister = int.Parse(txtVRegToRead.Text);
Var.cmd = 0;
Var.flags = 0;
Var.FloatVar = 0;
Var.IntegerIntVar = 0;
Var.DoubleVar = 0;
Var.precision = 6;
writeStatus.Text = "";
Var.type = CTC_Lib.Ctccom32v2.CT_VARIANT_INTEGER;
Var.IntegerIntVar = Convert.ToInt32(txtVRegVal.Text);
Var.taskHandle = 0;
results = CTC_Lib.Ctccom32v2.CtSetVRegister(CTconnection,ref Var);
if ((results == SUCCESS))
{
writeStatus.Text = "SUCCESS";
}
else
{
writeStatus.Text = "ERROR";
}
}
I get the error:
Use of unassigned local variable 'Var'
I am a bit puzzled as to how to properly pass the struct 'Var' to the VB Class library.
init variable
CTC_Lib.Ctccom32v2.CT_VARIANT Var = new CTC_Lib.Ctccom32v2.CT_VARIANT();
you must create instance of Var,
CTC_Lib.Ctccom32v2.CT_VARIANT Var = new CTC_Lib.Ctccom32v2.CT_VARIANT();

Categories