Convert C++ array of struct w/o tons of new calls? - c#

C++
typedef struct someStruct {
int val1, val2;
double val3;
} someStruct;
someStruct a [1000] = { {0, 0, 0.0}, {1, 1, 1.0}, ... };
The only way to initialize such a table in C# I know of is to write something like
class SomeStruct
{
int val1, val2;
double val3;
public SomeStruct (int val1, int val2, double val3)
{
this.val1 = val1;
this.val2 = val2;
this.val3 = val3;
}
}
SomeStruct[] a = new SomeStruct [1000]
{
new SomeStruct (0, 0, 0.0),
new SomeStruct (1, 1, 1.0),
...
};
Is there a way to have a be a (reference to) an array of values of type class SomeClass instead to pointers to those?
Edit:
The point is that I want to avoid having to call new for each struct in the array. So what I want is an array containg 1000 structs and not 1000 pointers to (1000) structs. The reason I am asking is that the way C# handles this appears insanely inefficent to me, involving a lot of memory and memory management overhead (over e.g. C++).
I had tried something like
struct SomeStruct {
int a, b;
double c;
}
SomeStruct[] a = new SomeStruct [1000] { {0,0,0.0}, {1,1,1.0}, ... };
But that wasn't possible. So though I know that structs are value types, I concluded that this is only true when passing them as parameters to function, and I had to use new, like this (using structs here):
struct SomeStruct {
int a, b;
double c;
SomeStruct (int a, int b, double c) {
this.a = a; this.b = b; this.c = c;
}
}
SomeStruct[] a = new SomeStruct [1000] {
new SomeStruct {0,0,0.0},
new SomeStruct {1,1,1.0},
...
};

You can use the struct keyword in C#. C# structs are value types- an array of structs is contiguously stored structs, identical to a C++ standard array.

It's ugly, but this will work (if you change the type to struct instead of class)
SomeStruct[] a = new SomeStruct [1000];
a[0].val1 = 0;
a[0].val2 = 1;
a[0].val3 = 2.0;
...
a[999].val1 = 0;
a[999].val2 = 1;
a[999].val3 = 2.0;
Edit:
If this is a global field, declare a as static readonly.

You can do this by creating a new collection for SomeStruct (derived from IEnumerable<>) Each item you use in the initialization syntax gets converted to a call to .Add(...), so provided your collection class has a method called Add (doesn't need to inherit from any other interface for this), with matching arguments, you can use the same C++ syntax.
eg.
public class SomeStructCollection : IEnumerable<SomeStruct> {
private readonly SomeStruct[] someStructs = new SomeStruct[1000];
private int currentIndex;
public void Add(int val1, int val2, double val3) {
someStructs[currentIndex++] = new SomeStruct(val1, val2, val3);
}
public SomeStruct this[int index] {
get { return someStructs[index];
}
//Implement IEnumerable<> interface.
}
Calling code can then wrap values in some blocks
SomeStructCollection coll = new SomeStructCollection {
{0, 0, 0.0}, {1, 1, 1.0}, { ... },
};

Related

C# - How to populate a custom class array containing integer primitives?

I have a simple C# program that contains a Coord class that stores an integer x and y value. I want to treat the Coord class like an array, as shown in the Main method. I have seen similar approaches to this in C++ and I would like to know the C# equivalent.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lab6 {
class Coord {
public int x;
public int y;
}
class Program {
static void Main(string[] args) {
Coord[] c = {{1, 2}, {5, 8}, {3, 40}, {6, 3}, {15, 12}, {1, 5}};
}
}
}
You have to put instances of Coord class in the Coord []
Coord[] c = new Coord[4];
c[0] = new Coord(1,3);
....
Or a better way
Coord[] c = {new Coord(1,2),new Coord(1,6)};
Dont forget to add the constructor and initialize the fields
public Coord(int x,int y){
this.x = x;
this.y = y;
}
In C# 9.0 (.NET 5), a record type would be best for this situation:
// Declaration
record Coord(int X, int Y);
// Implicit "new".
Coord[] c = new Coord[] { new(1, 2), new(5, 8) };
new() (with the type omitted) was also introduced in C# 9.0. This might get you closer to what you wanted originally.
Record types
This wasn't part of your question, but if you want immutable data, records are the way to go in new versions of C#. Positional records, like in the example above, are immutable: I don't how you plan on using your Coord type, but if you don't change the x or y value after instantiation, an immutable type is probably what you want.
If you are unable to use .NET 5, you might consider using a struct instead, for similar reasons.
From the record type docs (emphasis added):
You use class definitions to create object-oriented hierarchies that focus on the responsibilities and behavior of objects. You create struct types for data structures that store data and are small enough to copy efficiently. You create records when you want value-based equality and comparison, don't want to copy values, and want to use reference variables.
If you are using C#9, you can instead A. use a record class and B. rely on target-typed new with the generated constructor:
public record Coord(int X, int Y);
public void YourMethod() {
Coord[] c = { new(1,2), new(2,3) };
}
This also has the benefit that you can deconstruct the points into variables, which feels natural for a Coord type:
Coord[] c = { new(1,2), new(2,3) };
var (x, y) = c[0];
// you get withers too!
var cNew = c[0] with { X = 5 };
Without records you can still use target-typing so long as you have an appropriate constructor.
class Coord {
public int X { get; } // you should use properties, not exposed fields
public int Y { get; }
public Coord(int x, int y) => (X, Y) = (x, y);
}
// later
Coord[] c = { new(1,2), new(2,3) };
Or the best of all worlds (depending on your viewpoint), a mutable record with withers, deconstruction and simple target typing:
record Coord(int X, int Y) {
public int X { get; set; } = X;
public int Y { get; set; } = Y;
}
The best you can do with the code as-is looks like this:
Coord[] c = {
new Coord() {x=1,y=2},
new Coord() {x=5,y=8},
//...
};
We can improve slightly on this by adding a constructor:
class Coord
{
public int x;
public int y;
public Coord(int X, int Y) {x = X; Y=y;}
}
Which gets us to here:
Coord[] c = {
new Coord(1,2),
new Coord(5,8),
//...
};
But once you're open to changing the code for the type we can do all kinds of things:
class Coord
{
public int x;
public int y;
public Coord(int X, int Y) {x = X; Y=y;}
public static IEnumerable<Coord> SeqFrom2DIntArray(int[,] input)
{
for(int i=0;i<input.GetUpperBound(0);i++) Console.WriteLine(b[x,0]);
{
yield return new Coord(input[i,0], input[i,1]}; // can throw an exception if the input is bad
}
}
}
And now you can create your Coord objects like this:
//must be a separate line/variable/object for the initializer
int[,] b = {{1, 2}, {5, 8}, {3, 40}, {6, 3}, {15, 12}, {1, 5}};
var c = Coord.SeqFrom2DIntArray(c);
Or if you really need an array (hint: very often IEnumerable by itself is enough and will perform much better):
//must be a separate line/variable/object for the initializer
int[,] b = {{1, 2}, {5, 8}, {3, 40}, {6, 3}, {15, 12}, {1, 5}};
var c = Coord.SeqFrom2DIntArray(c).ToArray();
Which is very close to the original request and doesn't even need C# 9's new toys.

Issue for user operator from managed C++ in C#

I am wrapping some C++ code in managed C++ to access it in C#: I can not figure out how to make operators properly work in C#
I create in managed C++:
public ref class ClassCLI
{
public:
double val;
ClassCLI() {};
void operator ++() { val++; };
double% operator[](int i) { return val; }
};
This works in managed C++:
ClassCLI^ obj = gcnew ClassCLI();
obj++;
obj[0] = 12.0;
But in C#, I can not use the operators ++ or [] directly, I have to use some ugly name that defeats the purpose of operators.
var obj = new ClassCLI();
obj.op_Increment();
obj.op_Subscript(0) = 12.0;
Can one tell me what I am doing wrong ? I says on some posts that operators should be static for C#, it is easy for operator++ but not sure how to do for the operator[]
If you refer to
C++/CLI: how to overload an operator to accept reference types?
How to declare the default indexed property in C++/CLI interface
you can get an idea to implement your ClassCLI class.
Sample implementation:
C++
public ref class ClassCLI
{
public:
double val;
ClassCLI() {};
property double default[int]
{
double get(int index) { return val; }
void set(int index, double value) { val = value; }
}
static ClassCLI^ operator ++(ClassCLI^ c)
{
c->val++;
return c;
};
};
C#:
static void Main()
{
ClassCLI c = new ClassCLI();
Console.WriteLine(c.val);
c++;
Console.WriteLine(c.val);
c[0] = 12;
Console.WriteLine(c.val);
Console.Read();
}
Output:
0
1
12

how to implements change "int" value when using the extension method in c#

Recently, I met a problem that how to change "int" value when using the extension method, don't allow use keyword "ref" or "out":
static void Main(string[] args)
{
var a = 5;
var b = 6;
a.Swap(b);
Console.WriteLine("a={0},b={1}", a, b);
Console.ReadKey();
}
I want to implement the Swap method(exchange variable a and variable b) and final output like this:
a = 6,b = 5
Swap method needs to exchange variable a and variable b, The issue is assigned by my teacher.
My answer is :
unsafe static void Swap(this int a, int b)
{
int* pb = &b;
pb += 7;
int* pa = &a;
pa += 8;
int temp = *pa;
*pa = *pb;
*pb = temp;
}
But my teacher said it not good enough. Because the 7 and 8 will be affected by the C# compiler.
I really didn't know how to implements Swap method. I think the integer will be passed by value when passing into Swap, and can't change it unless finding out its original address.
Did I misunderstand something? Your thought would be appreciated.
added:
There is a lot of people said it doesn't make sense, and a lot of questions, I know it doesn't make sense. but it truly can do this. I will paste the answer to bellow after I got the answer from my teacher.
added 20190225
I get an answer from my teacher, below is the complete answer:
internal static class Program
{
static void Main(string[] args)
{
var (a, b) = (5,6);
a.Swap(b);
Console.WriteLine($"a=({a}),b=({b})");
Console.ReadKey();
}
private static void Swap<T>(ref this T op1, in T op2)
where T : struct
{
var temp = op1;
op1 = op2;
RefUnlocker.Unlock(op2) = temp;
}
}
public class RefUnlocker
{
private delegate ref T InToRef<T>(in T arg) where T : struct;
private static ref T RefWrapper<T>(ref T arg) where T : struct => ref arg;
private static readonly MethodInfo _refWrapper = typeof(RefUnlocker)
.GetMethod(nameof(RefWrapper), BindingFlags.Static | BindingFlags.NonPublic);
public static ref T Unlock<T>(in T arg) where T : struct
{
Delegate dgt = Delegate.CreateDelegate(typeof(InToRef<T>), _refWrapper.MakeGenericMethod(typeof(T)));
InToRef<T> itrf = (InToRef<T>)dgt;
return ref itrf(arg);
}
}
C# 7.2 provides a keyword in. The in modifier on parameters, to specify that an argument is passed by reference but not modified by the called method. Adding the in modifier to an argument is a source compatible change.
However you can use Delegate to modify the in parameter.
Thanks to my teacher deeply for this.
It is not at all clear why you are adding 7 and 8 to some pointers.
What do you hope to accomplish with that?
If the extension method is not essential, then the answer is easy!!
As Michael Randall wrote:
static unsafe void Swap(int* pa, int* pb)
{
int temp = *pb;
*pb = *pa;
*pa = temp;
}
// Call this with: Swap(&a,&b);
The best I could do with an extension is:
using System;
public static class Test
{
static unsafe void Swap(this int a, int* pa, int* pb)
{
*pa = *pb;
*pb = a;
}
public static unsafe void Main()
{
var a = 5;
var b = 6;
a.Swap(&a, &b);
Console.WriteLine("a={0},b={1}", a, b);
}
}
IDEOne Code
Results
Success #stdin #stdout 0.01s 131520KB
a=6,b=5
This is only to back up #abelenky's answer, not to be an answer in itself
Just with pointers, no extension, no ref, no out
public unsafe static void Swap(int* a, int* b)
{
var temp = *a;
*a = *b;
*b = temp;
}
Usage
public unsafe static void Main()
{
var a = 5;
var b = 6;
Swap(&a, &b);
Console.WriteLine("a={0},b={1}", a, b);
Console.ReadKey();
}
or another variation with a franken-extensions
public static unsafe class ext
{
public static int Swap(this int a, int* b)
{
var temp = *b;
*b = a;
return temp;
}
}
Usage
var a = 5;
var b = 6;
a = a.Swap(&b);
Console.WriteLine("a={0},b={1}", a, b);

C# Implicit/Explicit Byte Array Conversion

I have following problem. I want to convert an integer value or float value into an byte array. Normaly I use the BitConverter.GetBytes() method.
int i = 10;
float a = 34.5F;
byte[] arr;
arr = BitConverter.GetBytes(i);
arr = BitConverter.GetBytes(a);
Is there a possibility to do this with implicit/explicit methods??
arr = i;
arr = a;
and also the other way around??
i = arr;
a = arr;
You can do it through an intermediate class. The compiler won't do two implicit casts by itself, so you must do one explicit cast and then the compiler will figure out the second one.
The problem is that with implicit casts, you must either cast to or from the type you declare the cast in, and you cannot inherit from sealed classes like 'int'.
So, it is not elegant at all. Extension methods are probably more elegant.
If you declare the class below, you can then do things like:
byte[] y = (Qwerty)3;
int x = (Qwerty) y;
public class Qwerty
{
private int _x;
public static implicit operator byte[](Qwerty rhs)
{
return BitConverter.GetBytes(rhs._x);
}
public static implicit operator int(Qwerty rhs)
{
return rhs._x;
}
public static implicit operator Qwerty(byte[] rhs)
{
return new Qwerty {_x = BitConverter.ToInt32(rhs, 0)};
}
public static implicit operator Qwerty(int rhs)
{
return new Qwerty {_x = rhs};
}
}
you could create extension methods to clean up the calling code a little bit - so you'd end up with:
int i = 10;
float a = 34.5F;
byte[] arr;
arr = i.ToByteArray();
arr = a.ToByteArray();
The code for the extension methods would be something like:
public static class ExtensionMethods
{
public static byte[] ToByteArray(this int i)
{
return BitConverter.GetBytes(i);
}
public static byte[] ToByteArray(this float a)
{
return BitConverter.GetBytes(a);
}
}

Object --> Struct?

How do I take an Object and convert it into a struct and vice visa?
public void myMethod1(object myInputObject, out string myOutputString)
{
myInputObject = null;
myOutputString = "";
//Convert object into a struct, then do something
}
Define a struct and set fields values inside your method.
I suppose you want something like this: (pseudo code)
class myclass
{
public int a;
public float b;
}
struct somestruct
{
somestruct(int a, float b)
{
this.a = a;
this.b = b;
}
int a;
float b;
}
myclass mc = new myclass();
mc.a = 125;
mc.b = 12.5;
somestruct s = new somestruct(mc.a, mc.b); //all fields of mc are now in struct somestruct

Categories