How to convert an optional pointer argument from C ++ code to C #

I have a function in C ++ something like this:

// C++ bool Foo(int* retVal = NULL) { // ... if (retVal != NULL) *retVal = 5; // ... return true; } 

And I can use functions in two ways:

 int ret; Foo(&ret); Foo(); 

When I write code in C #, I used the ref keyword:

 // C# bool Foo(ref int retVal = null) { // ... if (retVal != null) { retVal = 5; } // ... return true; } 

but the compiler said:

The ref or out parameter cannot have a default value.

How can I solve this problem?

+5
source share
3 answers

The easiest way is to simply write overload:

 bool Foo() { int notUsed; return Foo(ref notUsed); } bool Foo(ref int retVal) { // ... retVal = 5; // ... return true; } 

If you really need to know if a ref value is needed, well, you can still use pointers anyway, but you'll need an unsafe context:

 unsafe bool Foo() { return Foo(null); } unsafe bool Foo(ref int retVal) { return Foo(&retVal); } private unsafe bool Foo(int* retVal) { // ... if (retVal != null) { *retVal = 5; } // ... return true; } 

Or, without unsafe , as indicated in the comments, since pointers to C # can be considered as heavy artillery:

 bool Foo() { var notNeeded = 0; return Foo(ref notNeeded, false); } bool Foo(ref int retVal) { return Foo(ref retVal, true); } private bool Foo(ref int retVal, bool retValNeeded) { // ... if (retValNeeded) { retVal = 5; } // ... return true; } 
+3
source

ref for C # is more like & (link) C ++ than * C and C ++ (pointer). As references to C ++, they must refer to something.

Now you can:

 public class OptionalRef<T> { public T Value { get; set; } public static implicit operator OptionalRef<T>(T value) { return new OptionalRef<T> { Value = value }; } public static implicit operator T(OptionalRef<T> optional) { return optional.Value; } public override string ToString() { return Value != null ? Value.ToString() : null; } } 

then

 static bool Foo(OptionalRef<int> retVal = null) { // ... if (retVal != null) { retVal.Value = 5; } // ... return true; } 

and you use it like:

 Foo(); // null passed Foo(null); // same Foo(5); // not interested if the value is changed // Full use OptionalRef<int> val = 5; Foo(val); int ret = val; 

note that I do not fully endorse the semantics I wrote

It’s rather a case when you asked for something, I gave you something, didn’t ask any questions

+3
source

I would do this in one of two ways. If you really want to have a reference to your object, you can wrap this in a class. They are always passed by reference, so you get your modification the way you want, and you can create it for null.

Here is an example.

 public class HolderObject { public string myStr {get; set;} } public class Program { public static void Main() { var xyz = new HolderObject() { myStr = "1234" }; Console.WriteLine(xyz.myStr); FixString(xyz); Console.WriteLine(xyz.myStr); FixString(); Console.WriteLine(xyz.myStr); } private static bool FixString(HolderObject input = null) { if (input != null) input.myStr = "test"; return true; } } 

prints

 1234 test 

Another solution is to overload your function.

 bool Foo() { // ... return true; } bool Foo(ref int retVal = null) { // ... if (retVal != null) { retVal = 5; } return Foo(); } 

I really don't like this. I'm actually in the middle of working on C # code that was pulled directly from C ++. Functions nested in 6 or 7 layers that deeply modify the object that was passed by reference. This is hard to read, and if you look at the code analysis warnings, it will suggest you not to use ref values.

If you can get as far as possible from going through ref and return the value that was changed back. Or pass back an object containing both your bool and your new value.

+2
source

All Articles