I have 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 ref keyword:
// C#
bool Foo(ref int retVal = null)
{
// ...
if (retVal != null)
{
retVal = 5;
}
// ...
return true;
}
but compiler said:
A ref or out parameter cannot have a default value.
How can I solve this problem?
Pointers as Argument in C programming language. Pointers as arguments can read/change the values of the variables that are pointed at. In other words we can say that through pointer as an argument we can modify the values of actual arguments of calling function.
The venerable book “ The C Programming Language ” by Brian Kernighan and Dennies Ritchie has this to say on pointer conversions: A pointer to one type may be converted to a pointer to another type. The resulting pointer may cause addressing exceptions if the subject pointer does not refer to an object suitably aligned in storage.
Example: Passing Pointer to a Function in C Programming. In this example, we are passing a pointer to a function. When we pass a pointer as an argument instead of a variable then the address of the variable is passed instead of the value. So any change made by the function using the pointer is permanently made at the address of passed variable.
Lets take an example to understand how this is done. In this example, we are passing a pointer to a function. When we pass a pointer as an argument instead of a variable then the address of the variable is passed instead of the value. So any change made by the function using the pointer is permanently made at the address of passed variable.
The simplest way would be to just write an overload:
bool Foo()
{
int notUsed;
return Foo(ref notUsed);
}
bool Foo(ref int retVal)
{
// ...
retVal = 5;
// ...
return true;
}
If you actually need to know whether the ref
value is needed, well, you can still use pointers, 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 suggested in the comments, as pointers in C# may 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;
}
The ref
of C# is more similar to the &
(reference) of C++ than to the *
of C and C++ (pointer). As C++ references, they must reference something.
Now, you could:
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'm not fully endorsing the semantics I wrote
It is more a case of you asked for something, I gave you something, no questions asked
I'd go about this one of two ways. If you REALLY want to have a reference to your object you can wrap that in a class. Those are always passed by reference so you'll get your modification the way you want and you can instantiate it to 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 code in C# that has been pulled directly from C++. Functions that are nested 6 or 7 layers deep modifying an object that was passed by reference. That is hard to read and if you look at the code analysis warnings, it will suggest you don't use ref values.
If you can I'd move away from passing by ref as much as possible and return the value back that has been modified. Or pass an object back that contains both your bool and your new value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With