C#: How to translate nested structures from C to C#? - c#

I have a program written in C which contains some nested structures of arrays like the following:
typedef struct
{
int s1var1[s1max1],
float s1var2[s1max2];
}struct1;
typedef struct
{
int s2var1[s2max1];
struct1 s2var2[s2max2];
*s2var2_ptr;
}struct2;
and I've written it in C# as following:
class Class1
{
public int[] s1var1 = new int[s1max1];
public float[] s1var2 = new float[s1max2];
}
class Class2
{
public int[] s2var1 = new int[s2max1];
public Class1[] s2var2 = new Class1[s2max2];
}
Is my translation true? What is wrong with this translation?
Thanks for your time.

public struct struct1
{
public int[] s1var1;
public float[] s1var2;
}
public struct struct2
{
public int[] s2var1;
public struct1[] s2var2;
}
public static void Main()
{
struct1 str;
str.s1var1 = new int[10];
str.s1var2= new float[10];
//or
struct1 str1 = new struct1();
str1.s1var1 = new int[10];
str1.s1var2= new float[10];
////
struct2 str2;
str2.s2var1 = new int[10];
str2.s2var2 = new struct1[10];
}
A struct type is a value type that is typically used to encapsulate
small groups of related variables, such as the coordinates of a
rectangle or the characteristics of an item in an inventory.
When a struct is created, the variable to
which the struct is assigned holds the struct's actual data. When the
struct is assigned to a new variable, it is copied. The new variable
and the original variable therefore contain two separate copies of the
same data. Changes made to one copy do not affect the other copy.
Microsoft source
Learn More About Structs
Classes and Structs

First, let's take a look at your code conceptually. In C you have some structures and in C# you have some classes. You will need to know that struct is different from class in many ways, not to mention that we have here some different languages as well, so writing a C# struct would be more suitable. However, if we look at your implementation, we see that on declaration level you try to assign some values to your arrays respectively. Are you sure the limits you use are defined and visible at the point you attempt to use them? Also, it would be much better if you would use a constructor and initialize your arrays there. And finally, I'm not sure at the point of Class2 you see Class1 which you attempt to use.

Related

How are arrays of structures allocated in C#

I am trying to allocate an array of structures in C#. For example,
public struct Channel {
int ChannelId;
// other stuff goes here...
}
public struct FrameTraffic {
public int FrameId;
public int MaxChannels;
public Channel[] Channels;
public FrameTraffic(int dummyCS0568 = 0)
{
this.FrameId = 0;
MaxChannels = TableMgr.MaxChannels;
Channels = new Channel[TableMgr.MaxChannels];
}
}
But when I go to allocate an array of FrameTraffic structures, I see that Channels is null. This tells me that Channels is a reference rather than an array of structures. Am I correct? If so, then allocating the Channels array shouldn't embed the array into the structure, but simply satisfy the reference in the structure. I want the structures embedded. Is there a way to do this? Or am I incorrect in my assumptions?
Answering the later part of your question and disregarding any other problem. Yes you are correct, this will be a reference to an array. However, if you wanted to embed the array in the struct you can use a fixed sized buffer using the fixed and unsafe keywords. However that can only be known at design time, also it can only be of the following value types and not a user defined struct.
bool, byte, char, short, int, long, sbyte, ushort, uint, ulong, float, or double.
So in short, what you want to do is not possible, you may need to clarify why you need this or re-think your problem
You need to use the correct marshalling attribute, and it needs to have a fixed size, say 40
public struct FrameTraffic
{
public int FrameId;
public int MaxChannels;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
public Channel[] Channels;
}
I was able to replicate the null issue not sure if its the same with yours :
There are two things that i think is possibly causing this :
You are just initializing the array with size but not assigning any values
You might be initializing FrameTraffic with default construct instead of what you have defined (this caused the actual NPE for me)
Below is how you can adjust your code: (I have hardcoded values which is brought by TableMgr.MaxChannels since i dont have that)
class Program
{
static void Main()
{
FrameTraffic fT = new FrameTraffic(0);
foreach (var item in fT.Channels)
{
Console.WriteLine(item.ChannelId);
}
Console.Read();
}
}
public struct Channel
{
public int ChannelId; //missing public exposer if you really want to reassign
// other stuff goes here...
}
public struct FrameTraffic
{
public int FrameId;
public Channel[] Channels;
public FrameTraffic(int dummyCS0568 = 0)
{
this.FrameId = 0;
const int MaxChannels = 1;
//array requires size and its values assigned here
Channels = new Channel[MaxChannels]{ new Channel { ChannelId = 1 } };
}
}

Why should we initialize a struct before passing it to a function?

Consider this code:
MyStruct j;
j.I = 3;
Console.WriteLine(j.I);
Now see this method:
public static void StructMod(MyStruct ms)
{
ms.I += 100;
Console.WriteLine(ms.I);
}
When we pass MyStruct to the method, should we initialize it before passing it? I.e.:
MyStruct j = new MyStruct()
Unless struct is value type?
Yes, it is.
First line from MSDN:
A struct type is a value type...
As with individual variables, a struct must be fully initialized before it can be used. Consider:
struct Foo
{
public int Bar;
public int Pop;
}
class Program
{
static void Main(string[] args) {
Foo f;
f.Bar = 3;
test(f); // ERROR: Use of unassigned local variable 'f'
}
static void test(Foo f) {
Console.WriteLine("{0}", f.Bar);
}
}
The solution here is to either initialize .Bar, or simply call the Foo constructor f = new Foo() which initializes all members to their default values.
This is the same logic behind the "Field ... must be fully assigned before control is returned to the caller" error that you get when adding parameterized constructors to structs.
After a little testing, it seems that either way you declare it, it's being initialized.
One reason to call new ... would be to execute code in the constructor, if any.
Take this sample from MSDN, for example:
public struct CoOrds
{
public int x, y;
public CoOrds(int p1, int p2)
{
x = p1;
y = p2;
}
}
You could just do this, and use c, but then x and y will be 0.
CoOrds c;
Alternatively, you could do this, and then x and y start off with values.
CoOrds c = new CoOrds(5,3);
(This would be more useful if the ctor did something more interesting.)
If you want the struct to have a particular value, then initialize it to that value.
If you want the struct to be initialized to its default value, then you don't need to explicitly initialize it. However, it might still be best to do so for the sake of readability if the struct's default value is non-obvious.
As a side note: Mutable structs are really bad; the entire scenario you propose in your example is a code smell. See Why are mutable structs “evil”?
The same behavior could be achieved more safely with an immutable struct like so
struct MyStruct
{
public readonly int I;
public MyStruct(int i_initial)
{
I = i_initial;
}
}
MyStruct j = new MyStruct(3);
public static void StructMod(MyStruct ms)
{
Console.WriteLine(ms.I + 100);
}
In particular, note that from the caller's point of view this function's behavior will be exactly the same as the one in the question, because structs are passed by value the same way that primitives like int are. If the "Mod" in StructMod is there because you expect this function to modify the value, then that's a good concrete example of why it's generally better for mutable types to be objects and not structs.

How do I convert to c# - passing a struct in C to a function?

In C I have this function:
void(MyStruct* ms){
ms->Prop1 = 2;
ms->Prop2 = 3;
}
With Struct
struct{
int Prop1;
int Prop2;
}MyStruct;
What is the equivalent of this in C#?
What I'm not sure about its two things:
In C# do I use a Struct or Class? Because I thought in C# structs are only value types.
Do I pass the struct or class with ref keyword?
As the code in C says *(a pointer to variable) you can use ref in C#. Also you can stick with struct unless you have any method implementations in that.
class is probably what you're looking for as in your example code you're passing around pointers and modifying the instance.
For more information see the MSDN Documentation:
A class is a reference type. When an object of the class is created, the variable to which the object is assigned holds only a reference to that memory. When the object reference is assigned to a new variable, the new variable refers to the original object. Changes made through one variable are reflected in the other variable because they both refer to the same data.
A struct is a value type. When a struct is created, the variable to which the struct is assigned holds the struct's actual data. When the struct is assigned to a new variable, it is copied. The new variable and the original variable therefore contain two separate copies of the same data. Changes made to one copy do not affect the other copy.
In general, classes are used to model more complex behavior, or data that is intended to be modified after a class object is created. Structs are best suited for small data structures that contain primarily data that is not intended to be modified after the struct is created.
As a class this could be represented simply as:
public class MyClass
{
public int Prop1 { get; set; }
public int Prop2 { get; set; }
}
And passed to a function as:
public void Test(MyClass s)
{
s.Prop1 = 2;
s.Prop2 = 3;
}
With no need for ref

Declare Two Dimensional Double Array Inside Structure

How can I declare a two dimensional double array inside the structure?
public struct PROBABILTY_SETUP
{
double[,] probablity[2,9613];
}
The above code NOT WORKING...
Because you're in a struct, you'd have to make it static, as you can't have an initializer for a non-static struct member (another option is use a constructor however).
If it was a class however, the below would work without the static keyword.
Try this:
public struct PROBABILITY_SETUP
{
static double[,] probablity = new double[2, 9613];
}
If you require more than one however, consider using a constructor
public struct PROBABILTY_SETUP
{
double[,] probablity;
public PROBABILTY_SETUP(double [,] probability)
{
this.probablity = probability;
}
}
You'll have to call the constructor with the array you require:
PROBABILITY_SETUP mySetup = new PROBABILITY_SETUP(new double[2, 9613]);

C# Struct / Lookup Table

Say I have a struct declared like the following:
public struct Test
{
public static int Width = 5;
...
public static int[] Value = new int[1]{ 0 };
}
Now what I want to do is call this from within another struct, but I have to clue how. What I'm trying to do would (in my mind) look like the following:
public struct AnotherStruct
{
public (type of struct) this[int key]
{
get
{
switch(key)
{
case 1:
return (another struct);
default:
return null;
}
}
}
}
My end goal is that I want to use code that looks like the following, without having to create an instance of the object:
structobject s = new AnotherStruct[5];
So this 'lookup table' will be created in another project and built, then called as a dll from my main project. Since I'm building the dll elsewhere and calling it, I'm hoping that I can get the dll loaded into memory once, and then I can just reference that memory from my main project. Then I'll have one allocated portion of memory and my code will just reference it, avoiding the need to create individual instances of this lookup table (thus avoiding the time overhead it takes to allocate the memory and store the new instance). The time I'd save would be hugely beneficial in the long run, so I'm hoping I can get this to work somehow.
I hope this isn't too confusing, but let me know if any clarification is needed.
Edit
This is being used on a website, so really I need an object that persists across all connections and is created once when the code is initially loaded. Same idea, but maybe that will make for a simpler solution?
Solution #2. Forgo the whole ID idea and just use the structure type and generics.
public struct St1
{
}
public struct St2
{
}
public class Factory<T>
where T : struct
{
static T _new = new T(); //cached copy of structure
public static T New { get { return _new; } }
}
class Program
{
static void Main(string[] args)
{
St1 x1 = Factory<St1>.New;
St1 x2 = Factory<St1>.New;
St1 x3 = Factory<St1>.New;
St2 y1 = Factory<St2>.New;
St2 y2 = Factory<St2>.New;
}
}
Solution #1. Using a common interface for all the structures and a dictionary collection
public interface IStr { }
public struct St1 : IStr
{
public static int ID = 1;
}
public struct St2 : IStr
{
public static int ID = 2;
}
public class StructFactory : System.Collections.ObjectModel.KeyedCollection<int, IStr>
{
public static StructFactory Default = new StructFactory();
protected override int GetKeyForItem(IStr item)
{
FieldInfo finfo = item.GetType().GetField("ID",
BindingFlags.Static | BindingFlags.Public);
return (int)finfo.GetValue(item);
}
public StructFactory()
{
Add(new St1());
Add(new St2());
}
}
class Program
{
static void Main(string[] args)
{
St1 x = (St1)StructFactory.Default[1];
St2 y = (St2)StructFactory.Default[2];
}
}
The syntax you use above won't work since it means "create an array of AnotherStruct with five elements in it." As mentioned in a comment, however, you really should look into using a factory pattern.
However, if you really want to use the pattern above, you could change it up slightly. Have your AnotherStruct array hold Type instances of each of your structs. Then, your "creation" line would look more like:
structobject s = (structobject)Activator.CreateInstance(AnotherStruct[5]);
You can use reflection on the Assembly (since you are wrapping it in a DLL) to get those Type objects.
And finally, unless you have a really good reason for using struct (and understand all of the nuances, of which there are several), stick with class.

Categories

Resources