VB code equivalent to C# for declaring struct - c#

I'm currently migrating some VB.Net code to C#, and am quite confused about the struct in VB.NET.
Here is the code from VB which I would like to ask the equivalent in C# or some explanation.
Below is the struct format
struct Pt_Appt
{
public Pt_Appt(int pID, int aID)
{
PatientID = pID;
AppointID = aID;
}
public int PatientID;
public int AppointID;
}
Below is the code that is confusing me, I've tried and it seems creating array of struct but why negative value.
Dim pt_appts(-1) As pt_appt

It declares an empty array of type pt_appt. The upper bound is set to -1. Since the lower bound is always 0, this results in no valid indices. Arrays are re-sized via ReDim. However, this should be avoided if possible. In most cases, a List(Of T) or similar structures are more appropriate.
The C# equivalent is
Pt_Appt[] pt_appts = new Pt_Appt[0];

Related

What is the exact equivalent to "KeyValuePair[] dataArray" (C#) in VB?

I need to call a C++ routine with a KeyValuePair parameter. I have an example in C#;
KeyValuePair[] dataArray =
new KeyValuePair[]{
new KeyValuePair() { key = 1234, value = "Atlanta" },
new KeyValuePair() { key = 70, value = "Atlanta" },
new KeyValuePair() { key = 2320, value = "999999999" }};
This seems to translates to;
Dim dataArray As KeyValuePair() = New KeyValuePair() {New KeyValuePair() With {
.key = 1234,
.value = "Atlanta"
}, New KeyValuePair() With {
.key = 70,
.value = "Atlanta"
}}
in VB.
I have two questions;
What is this structure called? I would call it an array of KeyValuePairs. So I know how to reference the structure when I search.
How does one add additional values dynamically?
EDIT:
More specifically I have a function whose purpose is to build the same type of structure statically built in the C# code above by reading values from a database. I had originally written the code assuming the "list of" key value pairs is what I needed. Here is that code;
Private Function buildDataRecord(ByRef objRecord As OracleDataReader) As List(Of KeyValuePair(Of Integer, String))
Dim i As Integer = 0
Dim lstFieldData As List(Of KeyValuePair(Of Integer, String)) = New List(Of KeyValuePair(Of Integer, String))
Dim strFieldName As String
On Error GoTo buildDataRecordError
For i = 0 To objRecord.FieldCount - 1
strFieldName = objRecord.GetName(i)
If strFieldName.Substring(0, 3) = "IN_" _
Then
lstFieldData.Add(New KeyValuePair(Of Integer, String)(CInt(strFieldName.Substring(3)), Trim(objRecord(i).ToString)))
End If
Next
Return lstFieldData
buildDataRecordError:
Err.Raise(Err.Number,
"buildDataRecord",
Err.Description,
Err.HelpFile,
Err.HelpContext)
When calling C++ I get the error;
Cannot marshal 'parameter #4': Generic types cannot be marshaled.
My assumption is I do not have the correct data type.
What is this structure called?
An Array of KeyValuePair. Arrays are CLR types shared by all languages.
How does one add additional values dynamically?
An array is a fixed-size data structure, so you don't just add additional items like you can with a List. But you can resize an array. VB has ReDim, or you can use the generic Array.Resize method that could also be used from C#.
C++ code rely a lot about how your memory is organized for your type.
C# generic type are just describing what the type should contains but nothing about memory organisation. Memory organisation is decided by JIT when it knows the true types of T1 and T2. JIT will probably align Item1 and Item2 on multiple of 8 in memory. It can store Item2 before Item1 (for example if item1 is byte and item2 an int). And in Debug the organisation can be different than in Release. This is why generic are not supported.
You have to define your own struct type for all not generic type versions of KeyValuePair you want to use. And I recommend you to use attribute like this to make thing explicit. Example if you want to handle KeyValuePair<byte, int>
[StructLayout(LayoutKind.Explicit)]
public struct KeyValuePairOfIntAndByte // For KeyValuePair<int, byte>
{
// note how fields are inversed in memory...
// this is the kind of optimisation JIT usually does behind your back
[FieldOffset(0)] public int Item2;
[FieldOffset(sizeof(int))] public byte Item1;
}
So make conversion of your KeyValuePair<int, byte> instance to an array of this struct and that should be ok.
Note that you will have to pin memory while your C++ code is using this C# array too... otherwise Garbage Collector can decide at any time to move your array elsewhere in memory (while your C++ code is using it...)
I strongly recommend you to read this: https://learn.microsoft.com/en-us/dotnet/framework/interop/copying-and-pinning if you want to continue on this way
For information Swig is a library that generate C# code for you that wrap C++ library so you can use C++ library as if it was written in C# (a lot simpler then...) without thinking too much about all the work you have to do. If you look at the generated code you will understand how complex it can be to do interop code right.

How to extract a struct array element into a variable without copying in C#?

I have a little question about arrays of struct in C#: lets say I have a struct Foo:
struct Foo
{
public string S;
public int X;
...
...
}
and I have an array of Foo:
Foo[] arr = ...
In one method, I use arr[i] quite often, so I'd like to keep it in a local variable (the expression for i is also a little long):
var f = arr[i]
Now, my problem is that I know structs are value type, which means assignments like this cause a copy. The struct is a little big (7 strings and a bool), so I'd prefer to avoid copying in this case.
If I am not mistaken, the only way to access the struct's fields without copying the struct is to use the array directly: arr[i].S or arr[i].X, but this quickly becomes annoying to read. I'd really like to keep the array element in a local variable, but I don't want to waste performance by copying it into the variable.
Is there a way to make something like a reference variable (similar to C++) to avoid copying? If not, than I'm curious if it's something the compiler optimizes?
How should I deal with this element? Can I put it in a local variable without copying or do I have to access it through the array to avoid copying?
Thanks in advance.
You can do this in C# 7 and later using ref local variables:
using System;
public struct LargeStruct
{
public string Text;
public int Number;
}
class Test
{
static void Main()
{
LargeStruct[] array = new LargeStruct[5];
// elementRef isn't a copy of the array value -
// it's really the variable in the array
ref LargeStruct elementRef = ref array[2];
elementRef.Text = "Hello";
Console.WriteLine(array[2].Text); // Prints hello
}
}
Of course, I'd normally recommend avoiding:
Large structs
Mutable structs
Public fields (although if it's mutable, doing that via public fields is probably best)
... but I acknowledge there are always exceptions.

How to copy an array of floats from c# to a C dll

I'm trying to copy an array of floats from my C# application to an array in a C-coded DLL.
Im used to programming in C#, not so much with C. However I have no problem doing the reverse procedure ie. reading an array of floats from a C coded DLL into my C# application. I've read several threads on this site but cant work out where Im going wrong.
C# CODE
[DllImport(#"MyDll")]
static extern int CopyArray(double[] MyArray);
double[] myValues = new double[100]
int a = 0;
while(a < 100)
{
myValues[a] = a;
a++;
}
CopyArray(myValues);
C++ DLL
This is the function header;
__declspec(dllexport) int CopyArray(float* Wavelengths);
This is the function code;
float theValues[100];
int CopyArray(float* theArray)
{
status = 0;
int count = 0;
while (count < 100)
{
theValues[count] = theArray[count];
++count;
}
return(status);
}
I'm expecting my C# array to end up in the C array "theValues" but that's not happening. There is nothing getting into "theValues" array.
A couple of things.
You are mixing data types and they are different lengths (float is 32bit and double is 64bit). Both types exist in both languages, but your caller and callee need to agree on the data type. Here is a list of data types and their managed/unmanaged equivalents.
The parameter you are sending is not a pointer. It might be translated to that automatically by the compiler, but there are several options. It is entirely possible that the compiler will pick one you don't want (more info here). The one you are probably looking for is [In]. If you want to get data back from C to C#, you will also want [Out]:
[DllImport(#"MyDll")]
static extern int CopyArray([In, Out]double[] MyArray);

Compare byte[] to T

I want to make a list of pointers to locations that contains a certain value in the process memory of another process. The value can be a short, int, long, string, bool or something else.
My idea is to use Generics for this. I have one problem with making it, how can I tell the compiler to what type he needs to convert the byte array?
This is what I made:
public List<IntPtr> ScanProccessFor<T>(T ItemToScanFor)
{
List<IntPtr> Output = new List<IntPtr>();
IntPtr StartOffset = SelectedProcess.MainModule.BaseAddress;
int ScanSize = SelectedProcess.MainModule.ModuleMemorySize;
for (int i = 0; i < ScanSize; i++)
if (ReadMemory(SelectedProcess, StartOffset + i, (UInt16)Marshal.SizeOf(ItemToScanFor)) == ItemToScanFor)
Output.Insert(Output.Count,StartOffset + i);
return Output;
}
How can I tell the compiler that he needs to convert the byte[] to type T?
Your question is a little bit confusing, but I'll try to answer what I can
Instead of taking a generic type, I would probably write a method that takes an instance of an interface like IConvertableToByteArray or something.
public IConvertableToByteArray
{
public byte[] ToByteArray();
}
Then If you needed to allow a specific type to be compatible with that method, you could make an encapsulating class
public IntConvertableToByteArray : IConvertableToByteArray
{
public int Value{get; set;}
public byte[] ToByteArray()
{
insert logic here
}
}
You could use Marshal.StructureToPtr to get an unmanaged representation of the structure (which has to be a 'simple' structure). You might need to special case strings though.
You should also think about the alignment constraints on what you are searching for -- advancing through memory 1 byte at a time will be very slow and wasteful if the item must be 4 or 8 byte aligned.

C# equivalent to VB6 'Type'

I am trying to port a rather large source from VB6 to C#. This is no easy task - especially for me being fairly new to C#.net. This source uses numerous Windows APIs as well as numerous Types. I know that there is no equivalent to the VB6 Type in C# but I'm sure there is a way to reach the same outcome. I will post some code below to further explain my request.
VB6:
Private Type ICONDIRENTRY
bWidth As Byte
bHeight As Byte
bColorCount As Byte
bReserved As Byte
wPlanes As Integer
wBitCount As Integer
dwBytesInRes As Long
dwImageOffset As Long
End Type
Dim tICONDIRENTRY() As ICONDIRENTRY
ReDim tICONDIRENTRY(tICONDIR.idCount - 1)
For i = 0 To tICONDIR.idCount - 1
Call ReadFile(lFile, tICONDIRENTRY(i), Len(tICONDIRENTRY(i)), lRet, ByVal 0&)
Next i
I have tried using structs and classes - but no luck so far.
I would like to see a conversion of this Type structure, but if someone had any clue as to how to convert the entire thing it would be unbelievably helpful. I have spent countless hours on this small project already.
If it makes any difference, this is strictly for educational purposes only.
Thank you for any help in advance,
Evan
struct is the equivalent. You'd express it like this:
struct IconDirEntry {
public byte Width;
public byte Height;
public byte ColorCount;
public byte Reserved;
public int Planes;
public int BitCount;
public long BytesInRes;
public long ImageOffset;
}
You declare a variable like this:
IconDirEntry entry;
Generally, in C#, type prefixes are not used, nor are all caps, except possibly for constants. structs are value types in C#, so that means that they are always passed by value. It looks like you're passing them in to a method that's populating them. If you want that usage, you'll have to use classes.
I'm not exactly sure what your issue is but this is a small ex of how to use a struct.
struct aStrt
{
public int A;
public int B;
}
static void Main(string[] args)
{
aStrt saStrt;
saStrt.A = 5;
}
Your question is not clear ..
What issues are you facing when you are using either struct or class and define those field members? Are you not able to access those members using an instance created for that class ??
Else, declare the class as static and make all the members inside the class also as static , so that u can access them without any instance being created!!
Maybe you trying to get something like this?
struct IconDirEntry
{
public byte Width;
// etc...
}
IconDirEntry[] tICONDIRENTRY = new IconDireEntry[tICONDIR.idCount - 1];

Categories