C# pointer reference - c#

Is there a way to create c++ style pointer in c#? I need this to set an int in several places when I don't know which int it is.
Like in c++ I would do:
int *i;
if(cond0) i = &someint;
if(cond1) i = &otherint;
if(cond2) i = &thirdint;
if(cond3) *i = someval;
if(cond4) *i = otherval;
if(cond5) *i = thirdval;
If I do this in c# style I will need 9 ifs and my program has much more conditions so its not feasible.
I thought of make some sort of value like:
int val;
if(cond3) val = someval;
if(cond4) val = otherval;
if(cond5) val = thirdval;
if(cond0) someint = val;
if(cond1) otherint = val;
if(cond2) thirdint = val;
but it's not possible because cond3, 4 and 5 are scattered along the program.

It is, but you have to wrap any code that does it in an unsafe block.
Alternatively, if this is happening in a method then you might be able to use the 'ref' keyword to pass a parameter in by reference.
Both of these options really constrain the solution to method boundaries. If you're dealing with anything more scattered than that, in C# it's probably better to try and find ways to reorganize your code to use less global state instead.

Yes, there is a type called IntPtr which I use for Windows handles.

Here's an example of C# pointers that illustrates both their declaration and how to wrap them in an unsafe block
Also, see the C# Programming Guide - Pointer Types

I'm not sure if you provided enough information in your question to give a correct answer, but one possible solution is to set the values in a function using ref parameters.
class Program
{
static void Main(string[] args)
{
var i = 1;
var someint = 2;
var otherint = 3;
var thirdint = 4;
Console.WriteLine("i: {0}\nsomeint: {1}\notherint: {2}\nthirdint: {3}", i, someint, otherint, thirdint);
SetInts(true, false, false, false, false, false, ref i, ref someint, ref otherint, ref thirdint);
Console.WriteLine("i: {0}\nsomeint: {1}\notherint: {2}\nthirdint: {3}", i, someint, otherint, thirdint);
Console.ReadKey();
}
static void SetInts(bool cond0, bool cond1, bool cond2, bool cond3, bool cond4, bool cond5, ref int i, ref int someint, ref int otherint, ref int thirdint)
{
if (cond0) i = someint;
if (cond1) i = otherint;
if (cond2) i = thirdint;
if (cond3) i = someint;
if (cond4) i = otherint;
if (cond5) i = thirdint;
}
}

Related

How to create mutable .NET strings?

.NET strings are always immutable, but how can one make an equivalent System.String class that the string values can be mutated?
For example: When a is changed, I want b also be changed.
var a = "Hello";
var b = a;
a = "World";
var shouldBeTrue = String.ReferenceEquals(a, b)
&& String.Equals(b, "World");
Strings are inmutable, wich was a very important design Decisions. It helps using them in Multitasking contexts and allows a bunch of other Optimizations like String Interning.
Usualy the inmutabiltiy is not a problem. Unless you are doing loads of string operations, what little dead strings accumulate can be dealt with by the GC whenver it coems around to running.
For the remaining cases, there is the StringBuilder class. Whose purpsoe is to get around inmutability and stuff like internening. On a more extreme level you might make your own Char list or array. Just do not forget to provide a custom ToString(). But for at least 95% of all cases the String and StringBuilder classes are enough.
Edit:
After reading a Comment to your Originbal post, I too noticed that mutabiltiy does not seem to be what you are actually looking for. Rather then you seem to look for is normal reference mechanics. While this thematic is somewhat related to inmutability, it is actually a distinct property. ref should work. As would be just making a class with a single string field and handing the instances of that class around.
As #Christopher noted, most likely what you really want is not string mutability, but rather a reference mechanic by which multiple such references are kept synchronized. The simplest such mechanism would be a wrapper class, like in the example below:
class Wrapper
{
public string Value { get; set; }
}
static void Main(string[] args)
{
Wrapper a = new Wrapper();
a.Value = "Hello";
Wrapper b = a;
a.Value = "World";
System.Diagnostics.Debug.Assert(ReferenceEquals(a, b));
System.Diagnostics.Debug.Assert(a.Value == b.Value);
}
var a = "Hello";
var b = a;
var chars = new char[] { 'W','o','r','l','d' };
unsafe
{
fixed (char* pTempChars = &a.GetPinnableReference())
{
char* ptr = pTempChars;
for (int i = 0; i < chars.Length; i++)
{
(*ptr) = chars[i];
ptr++;
}
}
}
var shouldBeTrue = String.ReferenceEquals(a, b) && String.Equals(b, "World");
//shouldBeTrue is true
But it can be dangerous. You must be sure that no one other than b and a refers to them. And it only works if the length of the string is the same.
Update(More readable but less flexible):
var a = "Hello";
var b = a;
ChangeString(ref a, "World");
var shouldBeTrue = String.ReferenceEquals(a, b) && String.Equals(b, "World");
//shouldBeTrue is true
___________________
var a = "Hello";
var b = a;
ChangeString(ref a, "Wor");
//b == "Worlo"
private bool ChangeString(ref string original, in string newValue)
{
if(original.Length < newValue.Length)
{
return false;
}
unsafe
{
fixed (char* pDest = original, pSource = newValue)
{
Buffer.MemoryCopy(
pSource,
pDest,
original.Length * sizeof(char),
newValue.Length * sizeof(char)
);
}
}
return true;
}
System.Text.StringBuilder Class is a mutable string. You can use the indexer to change the char in pos (one char only), and use the Insert, Replace, Append, and AppendLine to make changes to the StringBuilder itself in the fastest way possible. These methods return an instance to the same string builder object, so, you don't actually need to assign the return value.

PInvoke Pointer to struct including float array

I'm attempting to P Invoke a C library for use on a Xamarin android app.
Consider the following C structure:
typedef struct
{
bool myBool;
myOtherStruct sOtherStruct;
int myInt;
float myFloat;
float myFloatArray[1024];
float myFloatArray2[1024];
float myFloatArray3[20];
float myFloatArray4[30];
} sMyStruct;
This is called using the following function:
unsigned int initialise(sMyStruct* a_pMyStruct)
I've put this into a C# structure:
[StructLayout(LayoutKind.Sequential)]
public unsafe struct SMyStruct
{
bool myBool;
myOtherStruct sOtherStruct;
int myInt;
float myFloat;
public fixed float myFloatArray[1024];
public fixed float myFloatArray2[1024];
public fixed float myFloatArray3[20];
public fixed float myFloatArray4[30];
public unsafe float[] MyFloatArray
{
get
{
fixed (float* ptr = myFloatArray)
{
float[] array = new float[1024];
Marshal.Copy((IntPtr)ptr, array, 0, 1024 * sizeof(float));
return array;
}
}
}
public SMyStruct (bool MyBool, myOtherStruct otherStruct, int MyInt, float MyFloat)
{
myBool = MyBool;
sOtherStruct = myOtherStruct;
myInt = MyInt;
myFloat = MyFloat;
}
Here's my function in C# to invoke this:
[DllImport("libMylib")]
private static extern unsafe uint initialise(SMyStruct* a_pMyStruct);
I then call this function with:
public unsafe void init ()
{
SMyStruct initStruct;
uint result = initialise(&initStruct);
}
So what happens is the C function will return my structure with A LOT of data. I then pass the structure again into another C routine which uses these parameters for the rest of the program.
My issue is how do I get the float array data back into the correct structure variable so that I can pass it again? At current my code has been based on these questions:
Marshalling float Array to c# and
Marshalling complex struct to c#
But I've not managed to code this so I can pass the float array back to my struct without even seeing a compiler error (let alone failing when I test it!)
How do I get the float array data into my structure?
EDIT
After a couple of answers and comments, I'm adding what I was doing initially to try and add some clarity.
I get a compiler error when rather than using the "public unsafe float[]..." routine above I do this (within the struct):
public SMyStruct (bool MyBool, myOtherStruct otherStruct, int MyInt, float MyFloat, float* MyFloatArray, float* MyFloatArray2, float* MyFloatArray3, float* MyFloatArray4)
{
myBool = MyBool;
sOtherStruct = myOtherStruct;
myInt = MyInt;
myFloat = MyFloat;
myFloatArray = MyFloatArray;
myFloatArray2 = MyFloatArray2;
myFloatArray3 = MyFloatArray3;
myFloatArray4 = MyFloatArray4;
}
With this code I get the error "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement"
At this point I attempted to use the copy routine instead.
What I want is to ensure the fields myFloatArray, myFloatArray2 etc. to be populated with whatever the initialise function returns. FYI myBool, sOtherStruct etc. are populated as I expect.
If you don't need to access the data you can leave it as a pointer. Although it looks like you're responsible for the memory, so you'll need to alloc and later free the unmanaged memory you are using. Something like...
[DllImport("libMylib")]
private static extern uint initialise(IntPtr a_pMyStruct);
[DllImport("libMylib")]
private static extern uint anotherNativeMethod(IntPtr a_pMyStruct);
//...
//How big is myOtherStruct??
int size = 1 + ?? + 4 + 4 + (1024*4) + (1024*4) + (20*4) + (30*4);
//int size = Marhsal.SizeOf(SMyStruct);
IntPtr pMyStruct = Marshal.AllocHGlobal(size);
initialise(pMyStruct);
anotherNativeMethod(pMyStruct);
Marshal.FreeHGlobal(pMyStruct);
Note that you can still use the get the Marshaller to copy the pointer to your structure using Marshal.PtrToStructure but you no longer need to depend on it for your code.
I suspect that many of your problems are caused by you attempting to run before you can walk. You have attempted to make a complex struct with many members. Make a single mistake in one place, and nothing works anywhere.
So, how can we simplify? Well, the question you ask relates to the fixed buffers. To paraphrase the question you are asking:
How can I copy an array to and from a fixed buffer?
Let's deal with that by working with a simplified type that only contains a fixed buffer, and prove that we can copy to and from that buffer.
Your property getter is along the right lines. The biggest problem is that you pass an incorrect length. The final argument of the Marshal.Copy overload that you are calling is the number of elements. You erroneously pass the number of bytes. The setter is very similar in nature to the getter. It all looks like this:
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
public unsafe struct MyStruct
{
private const int floatArrayLength = 4;
private fixed float _floatArray[floatArrayLength];
public float[] floatArray
{
get
{
float[] result = new float[floatArrayLength];
fixed (float* ptr = _floatArray)
{
Marshal.Copy((IntPtr)ptr, result, 0, floatArrayLength);
}
return result;
}
set
{
int length = Math.Min(floatArrayLength, value.Length);
fixed (float* ptr = _floatArray)
{
Marshal.Copy(value, 0, (IntPtr)ptr, length);
for (int i = length; i < floatArrayLength; i++)
ptr[i] = 0;
}
}
}
}
class Program
{
static void WriteArray(float[] arr)
{
foreach (float value in arr)
{
Console.Write(value);
Console.Write(" ");
}
Console.WriteLine();
}
static void Main(string[] args)
{
MyStruct myStruct = new MyStruct();
WriteArray(myStruct.floatArray);
myStruct.floatArray = new float[] { 1, 2, 3, 4 };
WriteArray(myStruct.floatArray);
myStruct.floatArray = new float[] { 5, 6 };
WriteArray(myStruct.floatArray);
Console.ReadLine();
}
}
}
The output of the program is:
0 0 0 0
1 2 3 4
5 6 0 0
This building block shows you how to handle your fixed buffers. You can use the code from this program and be sure that the fixed buffers are handled correctly. When you move to a more complex structure, if you have any problems you can be confident that they are not related to the fixed buffer code.

Safe (in the C# sense) way to implement something with pointers

...
{
int *r1, *r2;
r1 = GetCorrectRegister(first);
r2 = GetCorrectRegister(second);
switch ((OpCode)current.opcode)
{
case OpCode.ADDR:
r2 = r1 + r2;
break;
}
}
...
This is the obvious, easiest way to solve this problem. However, I'd prefer not to use an unsafe method if I can avoid it. Basically, I have a bunch of integers which represent registers. There are assembly instructions that take register mnemonics as arguments. I'd prefer not to have the logic to determine which variable to assign to in each branch of the switch statement or make some sort of kludgey GetRegisterValue(mnemonic) and SetRegisterValue(mnemonic) functions. Is there some C#y way to do something similar?
I have a bunch of integers which
represent registers
The obvious thing here is not to have a bunch of integers. Create an array
int[] registers = new int[NUMBER_OF_REGISTERS];
Your above code turns into
{
int r1Index, r2Index;
r1Index = GetCorrectRegisterIndex(first);
r2Index = GetCorrectRegisterIndex(second);
switch ((OpCode)current.opcode)
{
case OpCode.ADDR:
registers[r1Index] = registers[r1Index] + registers[r2Index];
break;
}
}
Additionally, use an enum to create symbolic names for your register names where each name gives you the right index.
How about using a class and ref parameters?
class Registers
{
public int EAX;
public int EBX;
//...
public void ExecuteBinaryOperation(int opCode, ref int r1, ref int r2)
{
// ...
// binary operation ADD.
r2 = r1 + r2;
//...
}
}
and in code:
registers.ExecuteBinaryOperation(0, ref registers.EAX, ref registers.EBX);

Interesting "params of ref" feature, any workarounds?

I wonder if there's any way something like this would be possible for value types...
public static class ExtensionMethods {
public static void SetTo(this Boolean source, params Boolean[] bools) {
for (int i = 0; i < bools.Length; i++) {
bools[i] = source;
}
}
}
then this would be possible:
Boolean a = true, b, c = true, d = true, e;
b.SetTo(a, c, d, e);
Of course, this does not work because the bools are a value type so they are passed into the function as a value, not as a reference.
Other than wrapping the value types into reference types (by creating another class), is there any way to pass a variable into function by the reference (ref) while using params modifier?
This is not possible. To explain why, first read my essay on why it is that we optimize deallocation of local variables of value type by putting them on the stack:
https://web.archive.org/web/20100224071314/http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx
Now that you understand that, it should be clear why you cannot store a "ref bool" in an array. If you could, then you could have an array which survives longer than the stack variable being referenced. We have two choices: either allow this, and produce programs which crash and die horribly if you get it wrong -- this is the choice made by the designers of C. Or, disallow it, and have a system which is less flexible but more safe. We chose the latter.
But let's think about this a little deeper. If what you want is to pass around "thing which allows me to set a variable", we have that. That's just a delegate:
static void DoStuff<T>(this T thing, params Action<T>[] actions)
{
foreach(var action in actions) action(thing);
}
...
bool b = whatever;
b.DoStuff(x=>{q = x;}, x=>{r = x;} );
Make sense?
There isn't really a way. You could do something like this:
public static void Main(string[] args)
{
BooleanWrapper a = true, b = true, c = true, d = true, e = new BooleanWrapper();
b.SetTo(a, c, d, e);
}
public static void SetTo(this BooleanWrapper sourceWrapper, params BooleanWrapper[] wrappers)
{
foreach (var w in wrappers)
w.Value = sourceWrapper.Value;
}
public class BooleanWrapper
{
public BooleanWrapper() { }
public BooleanWrapper(Boolean value)
{
Value = value;
}
public Boolean Value { get; set; }
public static implicit operator BooleanWrapper(Boolean value)
{
return new BooleanWrapper(value);
}
}
But then again how is that any better than just doing this:
public static void Main(string[] args)
{
Boolean[] bools = new Boolean[5];
bools.SetTo(bools[1]); // Note I changed the order of arguments. I think this makes more sense.
}
public static void SetTo(this Boolean[] bools, Boolean value)
{
for(int i = 0; i < bools.Length; i++)
bools[i] = value;
}
After all, an array is a sequence of variables. If you need something that behaves like a sequence of variables, use an array.
Unfortunately the community of Java, and now .NET, developers decided that less flexibility in the name of "safety" is the preferred solution, and to achieve the same result with less lines of code you have to opt for extraordinary complexity (all those class structures, delegates, etc.).
In Delphi I could simply do something like this:
var
a: integer; f: double; n: integer;
sscanf(fmtstr, valuestr, [#a, #f, #n]);
//<-- "sscanf" is a function I wrote myself that takes an open array of pointers.
In C# You would have to do:
int a; double f; int n;
object [] o = new object[];
sscanf(fmtstr, valuestr, ref o);
a = o[0];
f = o[1];
n = o[2];
That's 5 lines of code to do what I could do in 1 line of Delphi code. I think there is a formula somewhere that the likelihood of bugs in code increases geometrically with the number of lines of code; so if you have 20 lines of code you're code is 4 times more likely to have bugs than if you have 10.
Of course, you can decrease your # lines of code by using the delegate with all those weird angle brackets and strange syntax, but I would think that's also a haven for bugs.
Here is some interesting solution:
public delegate RecursionRefFunc<T> RecursionRefFunc<T>(ref T arg);
public static RecursionRefFunc<T> Boo<T>(ref T input)
{
Console.WriteLine(input); // Work in here
return Boo;
}
public static void Main(string[] args)
{
int x1 = 1, x2 = 2, x3 = 3, x4 = 4, x5 = 5;
Boo(ref x1)(ref x2)(ref x3)(ref x4)(ref x5);
}
// Output: //
// 1
// 2
// 3
// 4
// 5
Delegate can declare in recursion.
Return a function outside and call again.
And you will be killed by the code reviewer.
Advertisement OW<: CWKSC/MyLib_Csharp
This would not be possible even if bools were reference types. While a class is a reference type, the variable in the Boolean[] is still a value, it's just that the value is a reference. Assigning the value of the reference just changes the value of that particular variable. The concept of an array of ref variables doesn't make sense (as arrays are, by their nature, a series of values).

Cannot use ref or out parameter in lambda expressions

Why can't you use a ref or out parameter in a lambda expression?
I came across the error today and found a workaround but I was still curious why this is a compile-time error.
CS1628: Cannot use in ref or out parameter 'parameter' inside an anonymous method, lambda expression, or query expression
Here's a simple example:
private void Foo()
{
int value;
Bar(out value);
}
private void Bar(out int value)
{
value = 3;
int[] array = { 1, 2, 3, 4, 5 };
int newValue = array.Where(a => a == value).First();
}
Lambdas have the appearance of changing the lifetime of variables that they capture. For instance, the following lambda expression causes the parameter p1 to live longer than the current method frame as its value can be accessed after the method frame is no longer on the stack
Func<int> Example(int p1) {
return () => p1;
}
Another property of captured variables is that changes to the variables are also visible outside the lambda expression. For example, the following code prints out 42
void Example2(int p1) {
Action del = () => { p1 = 42; };
del();
Console.WriteLine(p1);
}
These two properties produce a certain set of effects which fly in the face of a ref parameter in the following ways:
ref parameters may have a fixed lifetime. Consider passing a local variable as a ref parameter to a function.
Side effects in the lambda would need to be visible on the ref parameter itself. Both within the method and in the caller.
These are somewhat incompatible properties and are one of the reasons they are disallowed in lambda expressions.
Under the hood, the anonymous method is implemented by hoisting captured variables (which is what your question body is all about) and storing them as fields of a compiler generated class. There is no way to store a ref or out parameter as a field. Eric Lippert discussed it in a blog entry. Note that there is a difference between captured variables and lambda parameters. You can have "formal parameters" like the following as they are not captured variables:
delegate void TestDelegate (out int x);
static void Main(string[] args)
{
TestDelegate testDel = (out int x) => { x = 10; };
int p;
testDel(out p);
Console.WriteLine(p);
}
You can but you must explicitly define all the types so
(a, b, c, ref d) => {...}
Is invalid, however
(int a, int b, int c, ref int d) => {...}
Is valid
As this is one of the top results for "C# lambda ref" on Google; I feel I need to expand on the above answers. The older (C# 2.0) anonymous delegate syntax works and it does support more complex signatures (as well closures). Lambda's and anonymous delegates at the very least have shared perceived implementation in the compiler backend (if they are not identical) - and most importantly, they support closures.
What I was trying to do when I did the search, to demonstrate the syntax:
public static ScanOperation<TToken> CreateScanOperation(
PrattTokenDefinition<TNode, TToken, TParser, TSelf> tokenDefinition)
{
var oldScanOperation = tokenDefinition.ScanOperation; // Closures still work.
return delegate(string text, ref int position, ref PositionInformation currentPosition)
{
var token = oldScanOperation(text, ref position, ref currentPosition);
if (token == null)
return null;
if (tokenDefinition.LeftDenotation != null)
token._led = tokenDefinition.LeftDenotation(token);
if (tokenDefinition.NullDenotation != null)
token._nud = tokenDefinition.NullDenotation(token);
token.Identifier = tokenDefinition.Identifier;
token.LeftBindingPower = tokenDefinition.LeftBindingPower;
token.OnInitialize();
return token;
};
}
Just keep in mind that Lambdas are procedurally and mathematically safer (because of the ref value promotion mentioned earlier): you might open a can of worms. Think carefully when using this syntax.
And maybe this?
private void Foo()
{
int value;
Bar(out value);
}
private void Bar(out int value)
{
value = 3;
int[] array = { 1, 2, 3, 4, 5 };
var val = value;
int newValue = array.Where(a => a == val).First();
}
You can not use an out parameter directly in a lambda expression. The reason why you can not do that is explained in the other answers.
Workaround
But you can use a local temporary variable with for the inner function and, after the inner function has been executed, assign the out value from the inner function to the out value of the outer function:
private static int OuterFunc (int i_param1, out int o_param2)
{
int param2 = 0;
var del = () => InnerFunc (i_param1, out param2);
int result = del ();
o_param2 = param2;
return result;
}
private static int InnerFunc (int i_param1, out int o_param2)
{
o_param2 = i_param1;
return i_param1;
}
private static void Main (string[] args)
{
int result = OuterFunc (123, out int param2);
Console.WriteLine (result); // prints '123'
Console.WriteLine (param2); // prints '123'
}
Please note
The question was created in 2009. My answer was created in 2023 using C#10 and .NET 6. I don't know whether this answer had also worked back in 2009, which means, the code here might depend on enhancements to C# and .NET that might have been made in the meantime.
I will give you another example.
Description
The code below will throw out this error. Because the change brought by the lambda expression (i)=>{...} only works in the function test.
static void test(out System.Drawing.Image[] bitmaps)
{
int count = 10;
bitmaps = new System.Drawing.Image[count];
Parallel.For(0, count, (i) =>
{
bitmaps[i] = System.Drawing.Image.FromFile("2.bmp");
});
}
Solution
So, if you remove out of the parameter, it works.
static void test(System.Drawing.Image[] bitmaps)
{
int count = 10;
bitmaps = new System.Drawing.Image[count];
Parallel.For(0, count, (i) =>
{
bitmaps[i] = System.Drawing.Image.FromFile("2.bmp");
});
}
If you need out really, don't change the parameter in the lambda expression directly. Instead, use a temporary variable please.
static void test(out System.Drawing.Image[] bitmaps)
{
int count = 10;
System.Drawing.Image[] bitmapsTemp = new System.Drawing.Image[count];
Parallel.For(0, count, (i) =>
{
bitmapsTemp[i] = System.Drawing.Image.FromFile("2.bmp");
});
bitmaps = bitmapsTemp;
}

Categories

Resources