How to move two enumerators simultaneously? - c#

I have two big arrays of two readonly structs: A and B. I need to enumerate over them but I need to do it in the most optimized way.
readonly struct A {
long a;
long b;
long c;
long d;
long e;
long g;
}
readonly struct B {
byte a;
ushort b;
}
As you can see Type A is very large struct to copy it over and over again so I made my custom enumerator that returns this struct by reference (ref return). Type B doesn't need it because its' size is only 4 bytes. Now I need to make two enumerators move simultenously using only single foreach cycle because it doesn't look much native calling Enumerator's methods directly (i.e. MoveNext, Current) and so on.
My problem is that when I try to save two structs in one single aggregate struct A is copied and I lose my perfomance gain.
public readonly struct Aggregate
{
public readonly A ItemA;
public readonly B ItemB;
public Aggregate(A itemA, in B itemB)
{
ItemA = itemA;
ItemB = itemB;
}
}
The total size of this aggregate will have size of 56 bytes. It sounds logical that C# copies the struct when I assign it to the property of another struct. But what can I do with it? I need only the reference to the element of an array. Using unsafe code to get a pointer is not a right way, I think, because GC can move my array (if it's small enough and not located in LOH area).
So what solutions could you propose to me?

I don't know whether I understand your question correct or not, but your talking about arrays.
Assumption: Both are arrays of same size
You can do that
for (int i = 0; i < length; i++)
{
ref var aItem = ref arrayA[i];
ref var bItem = ref arrayB[i];
//do your stuff
}

You can use the enumerators explicitly, without a foreach-loop:
var aEnumerator = listA.GetEnumerator();
var bEnumerator = listB.GetEnumerator();
while (aEnumerator.MoveNext() && bEnumerator.MoveNext()) {
var aItem = aEnumerator.Current;
var bItem = bEnumerator.Current;
//TODO: do some work
}

Related

C++ how to implement an array of list

I'm translating a part of code from C# to C++.
Here is the point I am :
Class Point
{
public int X;
public int Y;
}
const int MAX = 256;
public void ComputePoints(Byte[] image,
int width,
int height,
out List<Point>[] listPixels)
{
listPixels = new List<Point>[MAX];
//etc..
}
(I simplified this piece of code to only show interesting part).
My Question concern the out List<Point>[] listPixels. I've try to translate this by :
public void ComputePoints(unsigned char[] image,
int width,
int height,
std::vector<Point> *listPixels[])
{
*listPixels = new std::vector<Point>[MAX];
//etc..
}
But I have error
Segmentation fault.
How can I write the simplest equivalent to out List<Point>[] listPixels in C++ ?
Since List<Point>[] is an array of lists, you could use a nested vector (vector of vector) to get the desired behaviour:
std::vector<std::vector<Point> >
Note that it could be important to add a space between the two >'s. Some compilers would not compile without.
Now you are able to pass the vector as reference like
void ComputePoints(... , std::vector<std::vector<Point> > &listPixels)
{
...
Why not return vector of vectors by value? In C++11 and newer it's fast and the code is easier to understand.
struct Point {
int x;
int y;
};
const int MAX = 256;
std::vector<std::vector<Point>> computePoints(const unsigned char image[], int width, int height) {
std::vector<std::vector<Point>> points(MAX);
// Here goes the code that does the calculations and fills 'points'.
return points;
}
For a fixed size array you could use std::array.
You don't need to use new in c++, you can simply use the stack, that's a common problem when transitioning from c#/java to c++.
For simple objects you nearly never need to dynamically allocate them (using new) and if you have to dynamically allocate them don't use raw owning pointers with new, use smart pointers (std::unique_ptr, std::shared_ptr).
It's not only the way create objects in c++, allocating objects on stack is also faster than the heap, plus you have better locality.
#include <list>
#incldue <array>
const int MAX = 256;
std::array<std::list<Point>, MAX> array_list;
i also like to type def such long types:
using MyContainer = std::array<std::list<Point>, 256>;
MyContainer array_list;
would be one way to have a array of lists
If you don't necessarily need a list, you could also use a std::vector(which should be your default container), which provides even more locality
For pre - C++11(as you'll find in other answers) you can also use std::vector instead of std::array, which will allocate the items on the heap, but this should be ok, because std::vector provide better functionality compared to plain C arrays.
Or if you really want to use C arrays:
Simply on stack:
std::list<Point> my_list_array[MAX];
and the heap allocated version:
std::list<Point>* my_list_array = new std::list<Point>[MAX];
//but don't forget about the delete[]!

How to access members of an struct like an array in C#?

Lets say I have a struct with more than hundred elements with complex names. And I am passing a struct of the struct type described to a function using ref, like this:
void Foo(ref mystruct a)
{
"I want to modify members or fields of struct a, like this:
a[0] = 10;
a[100] = 11;"
}
Thanks!
Maybe you should re-examine your choice of data structure. Perhaps a dictionary would be better suited?
It's a strange request as you're expecting the order of the fields to be significant, but I suspect you could do this through Reflection or the TypeDescriptor.
I would revise my code sample below to use proper property names with constants, but if you know the property names, just call the properties directly and save yourself from the reflection overhead. Otherwise, use a dictionary with constants.
/* yeah, probably not a good idea.
public void Foo(ref MyStruct a)
{
TypeDescriptor.GetProperties(a)[0].SetValue(a, 10);
}
*/
While you can use the struct LayoutKind attribute to force simple types to share memory like a "C" Union, you still cannot make an array share memory with simple types because ref types (aka garbage collected types) don't work with the attribute. The concept of C shortcuts like memset of a struct don't map to C# in any way, because C# is a safe language. In fact, that is a Good Thing. Many bugs have come from these kinds of memory addressing shortcuts.
If you want to simulate this behavior, create a class with properties that map to specific members of a backing array, but again, why do this? There are much better data structures to suit your needs in C# such as List, SortedList, Dictionary, Map, Stack, etc. that are safe.
You can do this in .NET BUT as several others have already posted: DO NOT DO IT.
Some Code
a.GetType().GetProperties() [0].SetValue (a, newvalue, null);
EDIT:
several reasons not to do this:
the order is not guaranteed !
what happens when there are no properties ?
what happens with readonly properties ?
So again: DO NOT DO THIS!
I will probably burn in hell, but...
Obviously horrible and not recommended and only works if your fields are all ints with default layout...
internal class Program
{
private struct MyStruct
{
//Must be all Int32
public int Field1, Field2, Field3;
}
private static void Main()
{
MyStruct str = new MyStruct {Field1 = 666, Field2 = 667, Field3 = 668};
int[] array = ToArray(str);
array[0] = 100;
array[1] = 200;
array[2] = 300;
str = FromArray(array);
}
private static int[] ToArray(MyStruct str)
{
IntPtr ptr = IntPtr.Zero;
try
{
int size = GetInt32ArraySize(str);
int[] array = new int[size];
ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(str, ptr, true);
Marshal.Copy(ptr, array, 0, size);
return array;
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
private static MyStruct FromArray(int[] arr)
{
IntPtr ptr = IntPtr.Zero;
try
{
MyStruct str = new MyStruct();
int size = GetInt32ArraySize(str);
ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(arr, 0, ptr, size);
str = (MyStruct)Marshal.PtrToStructure(ptr, str.GetType());
return str;
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
private static int GetInt32ArraySize(MyStruct str)
{
return Marshal.SizeOf(str) / Marshal.SizeOf(typeof(Int32));
}
}

Not able to modify object of struct in loop

I have a List of structure.In the loop i am trying to modify the object's property,which is happening,but when i (Quick look in Visual studio)look into the list object ,the new value is not reflecting.Is it by virtue that the structure's object cannot be modified when in a collection?
I am using generics list with the struct as the type in the list
You mention "modify the object's property" in the context of a struct, but importantly a struct is not an object. Other people have answered as to the issue with structs being copied (and changes discarded), but to take that further the real problem here is that you have a mutable (changeable) struct at all. Unless you are on XNA (or similar) there is simply no need.
If you want to be able to change properties, make it a class:
public class Foo {
public string Bar {get;set;}
}
This is now a reference-type, and your changes (obj.Bar = "abc";) will be preserved through the foreach. If you really want/need a struct, make it immutable:
public struct Foo {
private readonly string bar;
public string Bar { get {return bar; }}
public Foo(string bar) {this.bar = bar;}
}
Now you can't make the mistake of changing the value of a copy; you would instead have to use the indexer to swap the value (list[i] = new Foo("abc");). More verbose (and you can't use foreach), but correct.
But IMO, use a class. Structs are pretty rare, to be honest. If you aren't sure: class.
If you are using a foreach loop you probably got
Compiler Error CS1654
Error Message Cannot modify members of
'variable' because it is a 'read-only
variable type'
This error occurs when you try to
modify members of a variable which is
read-only because it is in a special
construct.
One common area that this occurs is
within foreach loops. It is a
compile-time error to modify the value
of the collection elements. Therefore,
you cannot make any modifications to
elements that are value types,
including structs.
You could however try
struct MyStruct
{
public int i;
}
List<MyStruct> list = new List<MyStruct>
{ new MyStruct { i = 1 }, new MyStruct { i = 2 } };
for(int i = 0; i < list.Count; i++)
{
MyStruct val = list[i];
val.i++;
list[i] = val;
}
EDIT
See also Structs Tutorial
Structs vs. Classes
Structs may seem similar to classes,
but there are important differences
that you should be aware of. First of
all, classes are reference types and
structs are value types.
I THINK i know what the problem might be.
struct Astruct
{
int amember;
}
List < Astruct > listofStructs;
foreach(Astruct A in listofStructs)
{
A.amember = 1337;
}
if this is what you are doing...
when you use structs in c# they are not referenced but copied! so that means the contents of your list is being COPIED to A, so when you change A it doesn't change the value in the list!
to solve this problem (if this is your problem...) either use CLASSES rather than STRUCTS, that way A would be a reference, OR use a manual iterating for loop instead, ie:
for(int i=0;i < listofStructs.Count;i++)
{
listofStructs[i].amember = 1337;
}
alternatively, if you’re using a list, you maybe should use an iterator or something... but the above should definitely fix that problem.
Given the information in your post (although I'd have liked to see the code itself), let me put forth the most probable issue and its fix.
foreach(var s in listOfStructs)
{
s.Property = x;
}
s is assigned to a copy of the actual struct in the collection. s.set_Property is now modifying the copy which is thrown away at the end of the current iteration.
This is because 2 value type variables cannot point to the same instance.
struct1 = new MyStruct(100, 200);
struct2 = struct1; // struct2 is now a copy of struct1
Now to the problem of how do you modify the instances in a collection:
Get the object to modify in a local variable (copy created). Modify it. Now remove the original object and insert the copy. use listOfStructs[i] = modifiedInstance.

C#: Good/best implementation of Swap method

I read this post about card shuffling and in many shuffling and sorting algorithms you need to swap two items in a list or array. But what does a good and efficient Swap method look like?
Let's say for a T[] and for a List<T>. How would you best implement a method that swaps two items in those two?
Swap(ref cards[i], ref cards[n]); // How is Swap implemented?
Well, the code you have posted (ref cards[n]) can only work with an array (not a list) - but you would use simply (where foo and bar are the two values):
static void Swap(ref int foo, ref int bar) {
int tmp = foo;
foo = bar;
bar = tmp;
}
Or possibly (if you want atomic):
Interlocked.Exchange(ref foo, ref bar);
Personally, I don't think I'd bother with a swap method, though - just do it directly; this means that you can use (either for a list or for an array):
int tmp = cards[n];
cards[n] = cards[i];
cards[i] = tmp;
If you really wanted to write a swap method that worked on either a list or an array, you'd have to do something like:
static void Swap(IList<int> list, int indexA, int indexB)
{
int tmp = list[indexA];
list[indexA] = list[indexB];
list[indexB] = tmp;
}
(it would be trivial to make this generic) - however, the original "inline" version (i.e. not a method) working on an array will be faster.
11 years later and we have tuples...
(foo, bar) = (bar, foo);
A good swap is one where you don't swap the contents. In C/C++ this would be akin to swapping pointers instead of swapping the contents. This style of swapping is fast and comes with some exception guarantee. Unfortunately, my C# is too rusty to allow me to put it in code. For simple data types, this style doesn't give you much. But once you are used to, and have to deal with larger (and more complicated) objects, it can save your life.
What about this?
It's a generic implementation of a swap method. The Jit will create a compiled version ONLY for you closed types so you don't have to worry about perfomances!
/// <summary>
/// Swap two elements
/// Generic implementation by LMF
/// </summary>
public static void Swap<T>(ref T itemLeft, ref T itemRight) {
T dummyItem = itemRight;
itemLeft = itemRight;
itemRight = dummyItem;
}
HTH
Lorenzo
Use:
void swap(int &a, int &b)
{
// &a != &b
// a == b OK
a ^= b;
b ^= a;
a ^= b;
return;
}
I did not realize I was in the C# section. This is C++ code, but it should have the same basic idea. I believe ^ is XOR in C# as well. It looks like instead of & you may need "ref"(?). I am not sure.
You can now use tuples to accomplish this swap without having to manually declare a temporary variable:
static void Swap<T>(ref T foo, ref T bar)
{
(foo, bar) = (bar, foo)
}
For anyone wondering, swapping can also be done also with Extension methods (.NET 3.0 and newer).
In general there seems not to be possibility to say that extension methods "this" value is ref, so you need to return it and override the old value.
public static class GeneralExtensions {
public static T SwapWith<T>(this T current, ref T other) {
T tmpOther = other;
other = current;
return tmpOther;
}
}
This extension method can be then used like this:
int val1 = 10;
int val2 = 20;
val1 = val1.SwapWith(ref val2);

How to reinterpret cast a float to an int? Is there a non-static conversion operator or user-defined assignment operator for conversion on 'this'? [duplicate]

This question already has answers here:
Convert int bits to float bits
(8 answers)
Closed 2 years ago.
1.
How can I reinterpret cast a float to an int (or a double to a long)?
float f = 2.0f;
int i = (int)f; // causes conversion
I only want to copy the bit-pattern from f to i. How can this be done?
2.
The implicit and explicit operators in C# uses one intermediate object because the operator function is static
public static implicit operator MyClass(double s)
{
return new MyClass(s);
}
..
..
MyClass m = 2.2; // this code uses 'm' and one intermediate object.
This is fine for reference types, but for value-types which are big (say 20-30 bytes), this will cause unnecessary data copy. Is my understanding correct? And If yes, then why doesn't C# have a non-static conversion operator or user-defined assignment operator so that the conversion/assignment takes place on 'this'? If it does, whats the way to do it?
1: BitConverter (as sixlettervariables) is an option; as is unsafe code (which doesn't need an intermediate buffer):
float f = 2.0f;
int i;
// perform unsafe cast (preserving raw binary)
unsafe
{
float* fRef = &f;
i = *((int*)fRef);
}
Console.WriteLine(i);
// prove same answer long-hand
byte[] raw = BitConverter.GetBytes(f);
int j = BitConverter.ToInt32(raw, 0);
Console.WriteLine(j);
2: note that you should limit the size of structs. I can't find a citation fr it, but the number "16 bytes" (max, as a recommendation) seems to stick in my mind. Above this, consider an immutable reference-type (class).
Barring unsafe code - this is the fastest method I know of to perform a reinterpret:
[StructLayout(LayoutKind.Explicit)]
private struct IntFloat
{
[FieldOffset(0)]
public int IntValue;
[FieldOffset(0)]
public float FloatValue;
}
private static float Foo(float x)
{
var intFloat = new IntFloat { FloatValue = x };
var floatAsInt = intFloat.IntValue;
...
Hope this helps someone.
The BitConverter class can retrieve the bytes for any primitive type, which you can then use to create an int. Another option is Buffer.BlockCopy if you have large amounts of converting to do.
float ff = 2.0f;
int ii = BitConverter.ToInt32(BitConverter.GetBytes(ff), 0);
float[] ff = new float[...];
int[] ii = new int[ff.Length];
Buffer.BlockCopy(ff, 0, ii, 0, ff.Length * 4); // byte-wise copy of ff into ii
No there is no other option given in C#, however, I think that while you're correct in the sense that there will be a copy made, any sufficiently simple implementation will have JIT optimizations done, possibly removing the need for a copy.
This approach, while unsafe, works as a generic solution
static unsafe TDest ReinterpretCast<TSource, TDest>(TSource source)
{
var tr = __makeref(source);
TDest w = default(TDest);
var trw = __makeref(w);
*((IntPtr*)&trw) = *((IntPtr*)&tr);
return __refvalue(trw, TDest);
}
This should be the fastest and cleanest way to do it:
public static class ReinterpretCastExtensions {
public static unsafe float AsFloat( this int n ) => *(float*)&n;
public static unsafe int AsInt( this float n ) => *(int*)&n;
}
public static class MainClass {
public static void Main( string[] args ) {
Console.WriteLine( 1.0f.AsInt() );
Console.WriteLine( 1.AsFloat() );
}
}

Categories

Resources