3

I have a structure definition as follows:

public struct check
{
    public int[] x = new int[3]; //error
}

This is an error because you cant define an array size for a structure member in C#. I cant define the space for this array even in a default constructor in C# because parameterless constructors aren't allowed.

How do I do it? I know structures are immutable in C#.

I am using this structure not to create new objects but just to typecast objects of other class types.

check corp = (check )WmUtils.WM_GetObj(Attr);

Wm_getObj returns an object of check2 class type. Is readonly keyword helpful here?

1
  • Structures are not innately immutable in C#. It's just a really bad idea to have them be mutable, as it can lead to all sorts of problems. Commented Oct 28, 2013 at 17:36

6 Answers 6

2

You can't have a parameter less constructor and you can't define an array with size in struct, this leaves you with a structure constructor taking a size as parameter like:

public struct check
{
    public int[] x;
    public check(int size)
    {
        x = new int[size];
    }
}
Sign up to request clarification or add additional context in comments.

10 Comments

This works for sure I know but I dont want a size to be passed when creating the object because the size is always fixed as 3.
If the size is always 3, why not just create 3 int variables?
And if the size is 100?
@TylerDurden, why not use a class instead of structure ?
You say this works, but how is it initializing from the class? It isn't. It is just creating an int array of default values.
|
2

How about a fixed array buffer:

public unsafe struct Buffer
{
    const int Size=100;
    fixed byte data[Size];

    public void Clear()
    {
        fixed(byte* ptr=data)
        {
            // Fill values with 0
            for(int i=0; i<Size; i++)
            {
                ptr[i]=0;
            }
        }
    }

    public void Store(byte[] array, int index)
    {
        fixed(byte* ptr=data)
        {
            // find max elements remaining
            int N=Math.Min(index + array.Length, Size) - index;
            // Fill values from input bytes
            for(int i=0; i<N; i++)
            {
                ptr[index+i]=array[i];
            }
        }
    }

    public byte[] ToArray()
    {
        byte[] array=new byte[Size];
        fixed(byte* ptr=data)
        {
            // Extract all data
            for(int i=0; i<Size; i++)
            {
                array[i]=ptr[i];
            }
        }
        return array;
    }
}

unsafe class Program
{
    static void Main(string[] args)
    {
        Buffer buffer=new Buffer();
        // buffer contains 100 bytes
        int size=sizeof(Buffer);
        // size = 100
        buffer.Clear();
        // data = { 0, 0, 0, ... }
        buffer.Store(new byte[] { 128, 207, 16, 34 }, 0);

        byte[] data=buffer.ToArray();
        // { 128, 207, 16, 34, 0, 0, ... }
    }
}

(PS need to compile with allow unsafe code)

2 Comments

It barks more than it bites. When done right it is perfectly safe. Just keep it simple. I hate they used a word like unsafe for what is should be like legacy or allow pointers.
You are right! Its actually my mental block with it connotation
2

How about this:

struct Check
{
  private int[] _x ;
  public int[] X { get { return _x ?? new int[3]{0,0,0,} ; } }
}

This delays instantiation of the internal array until it is referenced. Presumably the array reference remains unchanged across the lifetime of the instance, so you don't really need a set accessor. The only real drawback here is that this is not thread-safe due to the implicit race condition on the first reference to the property X. However, since your struct putatively lives on the stack, it would seem that that is probably not a huge issue.

Comments

1

Use a class instead of a structure.

2 Comments

Brilliant answer. In Tyler Durden, we trust!
but if you want to cast, you'll still need to define the operators!
1

Given a check2 class:

  public class check2
  {
     public int x1 { get; set; }
     public int x2 { get; set; }
     public int x3 { get; set; }
  }

In your struct with a integer array, just add an operator to cast it from the class. The operator can initialize the array from the class instance:

  public struct check
  {
     public int[] x;

     public static explicit operator check(check2 c2)
     {
        return new check() { x = new int[3] { c2.x1, c2.x2, c2.x3 } };
     }
  }

Now you can create a check2 class and cast it to a check struct:

  check2 c2 = new check2() { x1 = 1, x2 = 2, x3 = 3 };
  check s = (check)c2;
  Console.WriteLine(string.Format("{0}, {1}, {2}", s.x[0], s.x[1], s.x[2]));

This outputs 1, 2, 3

2 Comments

Actually its not always check2 typecasted, sometimes other structs too
You'll need to define an operator for each of them. There may be some shared code between them, but ultimately each conversion has to be defined.
0

This will probably help a lot. I have created structure MyX, Struct contains methods ToByte and to Struct So if you have byte array you can fill your struct array with bytes But be sure that your byte array alignment is correct. Hope this helps.

    public struct MyX
    {
        public int IntValue;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U1)]
        public byte[] Array;

        MyX(int i, int b)
        {
            IntValue = b;
            Array = new byte[3];
        }

        public MyX ToStruct(byte []ar)
        {

            byte[] data = ar;//= { 1, 0, 0, 0, 9, 8, 7 }; // IntValue = 1, Array = {9,8,7}
            IntPtr ptPoit = Marshal.AllocHGlobal(data.Length);
            Marshal.Copy(data, 0, ptPoit, data.Length);

            MyX x = (MyX)Marshal.PtrToStructure(ptPoit, typeof(MyX));
            Marshal.FreeHGlobal(ptPoit);

            return x;
        }
        public byte[] ToBytes()
        {
            Byte[] bytes = new Byte[Marshal.SizeOf(typeof(MyX))];
            GCHandle pinStructure = GCHandle.Alloc(this, GCHandleType.Pinned);
            try
            {
                Marshal.Copy(pinStructure.AddrOfPinnedObject(), bytes, 0, bytes.Length);
                return bytes;
            }
            finally
            {
                pinStructure.Free();
            }
        }
    }

    void function()
    {
        byte[] data = { 1, 0, 0, 0, 9, 8, 7 }; // IntValue = 1, Array = {9,8,7}
        IntPtr ptPoit = Marshal.AllocHGlobal(data.Length);
        Marshal.Copy(data, 0, ptPoit, data.Length);

        var x = (MyX)Marshal.PtrToStructure(ptPoit, typeof(MyX));
        Marshal.FreeHGlobal(ptPoit);

        var MYstruc = x.ToStruct(data);


        Console.WriteLine("x.IntValue = {0}", x.IntValue);
        Console.WriteLine("x.Array = ({0}, {1}, {2})", x.Array[0], x.Array[1], x.Array[2]);
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.