7

Is there a specific reason why C# 7 bring inlining out parameters but not ref?

The following is valid on C# 7:

int.TryParse("123", out _);

But this is invalid:

public void Foo(ref int x) { }

Foo(ref _); // error

I don't see a reason why the same logic can't be applied to ref parameters.

Selman Genç
  • 100,147
  • 13
  • 119
  • 184
  • 1
    Would it be because the semantic is different? With `out` you expect a result, with `ref` you pass in a reference. – dcg Apr 14 '17 at 13:24
  • 4
    What do you propose the value of the parameter should be on input? `default(T)`? – Jeroen Mostert Apr 14 '17 at 13:24
  • @JeroenMostert sure, why not ? – Selman Genç Apr 14 '17 at 13:27
  • 1
    `ref` means that parameter's value passed can be used in the `Foo` method; however *uninitialized* local variable - `Foo(ref _)` - contains trash. – Dmitry Bychenko Apr 14 '17 at 13:27
  • @ZizyArcher except, as OP clearly states in his question, it was changed in C# 7. Second sentence :| – decPL Apr 14 '17 at 13:32
  • 1
    @SelmanGenç: I'm just trying to make your feature request complete before you post it on Github. :-P Honestly, though, I see this as much less useful than the same for `out` -- and that isn't even such a hot feature to begin with. What (realistic) methods take `ref` parameters that you'd want to ignore entirely, and work correctly when you pass "the default" for that particular type? – Jeroen Mostert Apr 14 '17 at 13:32
  • @JeroenMostert I come across this while writing unit tests, there is a method I was testing and I only care about one parameter, there were two refs that I don't care. this feature would be useful there :) now thinking about it maybe I should change those refs to out... – Selman Genç Apr 14 '17 at 13:34
  • @ZizyArcher Well, his explicitly asking why it is so (works for `out`, not for `ref`). So I'm not sure what you're trying to say here. – decPL Apr 14 '17 at 13:36
  • 1
    @SelmanGenç Do your methods actually use the values passed in to those `ref` parameters? If not, why are you using `ref`. In 9 years of writing C#, I think I've probably used `ref` once. It's not a very widely used feature, so I question why you have a method that takes two of them. – JLRishe Apr 14 '17 at 13:36
  • I've never seen a method that used `ref` and couldn't be improved by introducing either a class or a tuple to get/return the things it was twiddling, or making it a method of a new class. It's OK for a first approach, I suppose, but it becomes tedious quickly enough that you bite the bullet and improve the signature. But that's a subjective discussion more appropriate for the feature request itself, I suppose. And by extension, this isn't such a good question for SO. – Jeroen Mostert Apr 14 '17 at 13:39
  • @JLRishe looks like I read the value of one parameter but the other one is only used to set a value. so I will change that one to out. – Selman Genç Apr 14 '17 at 13:47
  • @jeroen-mostert the same can be said for `out` parameters. These features exactly allow one not to have to mess with tuples, classes and extra methods. – chase Apr 21 '19 at 05:09

1 Answers1

12

The reason is simple: because you're not allowed to pass an uninitialized variable into a ref parameter. This has always been the case, and the new syntactical sugar in C#7 doesn't change that.

Observe:

int i;
MyOutParameterMethod(out i);  // allowed

int j;
MyRefParameterMethod(ref j);  // compile error

The new feature in C#7 allows you to create a variable in the process of calling a method with an out parameter. It doesn't change the rules about uninitialized variables. The purpose of a ref parameter is to allow passing an already-initialized value into a method and (optionally) allow the original variable to be changed. The compiler semantics inside the method body treat ref parameters as initialized variables and out parameters as uninitialized variables. And it remains that way in C#7.

JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • 2
    While accurate, this is missing the point. Initializing to default would've been perfectly reasonable. Consider `Thingie MakeThingie ( ref string locationWhereToPutThingie )` that uses predefined location unless provided. Thingies don't care enough about their location for it to be made a part of them, callers sometimes may not care about location either. `MakeThingie ( ref _ )` seems easy enough. – chase Apr 21 '19 at 05:03