While porting a C++ application to C# recently, I needed to translate code like this:
bool myFunction(int param, int *a1, int *a2, char *b1, char *b2, bool *c1, bool *c2)
{
....
}
void otherFunction()
{
bool looped = false;
[...]
if(myFunction(5, nullptr, nullptr, nullptr, nullptr, &looped, nullptr))
{
[...]
}
[...]
}
In C#, it gives something like this:
public bool myFunction(int param, out int a1, out int a2, out string b1, out string b2, out bool c1, out bool c2)
{
var looped = false;
int temp_a1, temp_a2;
string temp_b1, temp_b2;
bool temp_c2;
[...]
if(myFunction(5, out temp_a1, out temp_a2, out temp_b1, out temp_b2, out looped, out temp_c2))
{
[...]
}
[...]
}
As you can see, here I need to create lots of unneeded temporary variables.
These parameters aren't used here, but are used elsewhere in the code, so they are needed.
The thing here would be to make something like this:
if(myFunction(5, out null, out null, out null, out null, out looped, out null))
Where the out null
means that the values passed "won't go anywhere", like if you did echo "text" > /dev/null
Also by the way, where'd the declaration expressions (#254) go?
1) Why do you have that many out parameters if they don't do anything?
2) If you have that many out parameters, you'd be better off just making an object to hold them
public class ResultObject
{
public int A1 { get; }
public int A2 { get; }
public string B1 { get; }
public string B2 { get; }
public bool Looped { get; }
public bool C2 { get; }
public bool Success { get; }
}
//elsewhere
public ResultObject MyFunction(int param)
{
//....
}
//usage
var result = MyFunction(someInt);
if (result.Success)
{
//....
}
These parameters are used, but not here. What I want is that when I don't use them I don't need to create lots of variables that I won't use just for storing the result of the out
s
So again, it makes a lot more sense to just put them all into one object and use that instead. Heck, make it a struct
if you want to avoid heap allocations. This just seems to be less of a useful language feature and more Round Peg->Square Hole.
Besides, if you put them in the function, they HAVE to have values, so you MUST use them each time. What you're doing actually gets you FURTHER from your goal. C#, by nature, MAKES you assign values to ANY parameter present. ANY of them.
With out var
you can write myFunction(5, out var temp1, out var temp2)
but _if_ complete patterns were allowed in this context, you might be able to write myFunction(5, out let *, out let *, ..)
to ignore the out
parameters.
This is the problem of converting code from one language to another: the idioms of the languages are different. So you need to redesign the code, not just copy/paste with syntax changes. The way to handle this with C# 7 will be to use a tuple:
(bool success, int a1, int a2, int b1, int b2, int c1, int c2) myFunction(int param)
{
....
}
void otherFunction()
{
var looped = false;
[...]
var myFunctionResult = myFunction(5);
if(myFunctionResult.success)
{
looped = myFunctionResult.c1;
[...]
}
[...]
}
In the meantime @Joe4evr's suggestion of a return type is the most idiomatic C# solution.
Wildcard syntax https://github.com/dotnet/roslyn/issues/20#issuecomment-70366000 #8074 could be extended to take care of this case.
E.g. testing if something is parsable without worrying about the result:
if (!int.TryParse(input, out *))
Console.WriteLine("Error: not a valid integer value.");
PS: I wouldn't fixate on refactoring the original C++ example too much. Sometimes we have to deal with the code that is outside of our control.
The C# 7 language feature of discards addresses this feature request. You can put out _
for each out argument you want to omit.