Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: out void/null #10799

Closed
zdimension opened this issue Apr 22, 2016 · 9 comments
Closed

Proposal: out void/null #10799

zdimension opened this issue Apr 22, 2016 · 9 comments
Labels
Area-Language Design Discussion Resolution-Fixed The bug has been fixed and/or the requested behavior has been implemented

Comments

@zdimension
Copy link

zdimension commented Apr 22, 2016

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?

@zdimension zdimension changed the title Proposal: out void Proposal: out void/null Apr 22, 2016
@Joe4evr
Copy link

Joe4evr commented Apr 22, 2016

  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)
{
    //....
}

@zdimension
Copy link
Author

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 outs

@Joe4evr
Copy link

Joe4evr commented Apr 22, 2016

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.

@121GWJolt
Copy link

121GWJolt commented Apr 22, 2016

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.

@alrz
Copy link
Contributor

alrz commented Apr 23, 2016

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.

@HaloFour
Copy link

#6183 is probably your best bet, that way you can at least declare the throwaway variables inline with the method call.

@DavidArno
Copy link

DavidArno commented Apr 23, 2016

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.

@dsaf
Copy link

dsaf commented Apr 25, 2016

Wildcard syntax #20 (comment) #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.

@gafter
Copy link
Member

gafter commented Mar 24, 2017

The C# 7 language feature of discards addresses this feature request. You can put out _ for each out argument you want to omit.

@gafter gafter closed this as completed Mar 24, 2017
@gafter gafter added the Resolution-Fixed The bug has been fixed and/or the requested behavior has been implemented label Mar 24, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Language Design Discussion Resolution-Fixed The bug has been fixed and/or the requested behavior has been implemented
Projects
None yet
Development

No branches or pull requests

8 participants