{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/118","labels_url":"https://api.github.com/repos/dotnet/roslyn/issues/118/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/roslyn/issues/118/comments","events_url":"https://api.github.com/repos/dotnet/roslyn/issues/118/events","html_url":"https://github.com/dotnet/roslyn/issues/118","id":55792161,"number":118,"title":"Proposal: Ref Returns and Locals","user":{"login":"stephentoub","id":2642209,"avatar_url":"https://avatars.githubusercontent.com/u/2642209?v=3","gravatar_id":"","url":"https://api.github.com/users/stephentoub","html_url":"https://github.com/stephentoub","followers_url":"https://api.github.com/users/stephentoub/followers","following_url":"https://api.github.com/users/stephentoub/following{/other_user}","gists_url":"https://api.github.com/users/stephentoub/gists{/gist_id}","starred_url":"https://api.github.com/users/stephentoub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stephentoub/subscriptions","organizations_url":"https://api.github.com/users/stephentoub/orgs","repos_url":"https://api.github.com/users/stephentoub/repos","events_url":"https://api.github.com/users/stephentoub/events{/privacy}","received_events_url":"https://api.github.com/users/stephentoub/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dotnet/roslyn/labels/1%20-%20Planning","name":"1 - Planning","color":"cccccc"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Area-Language%20Design","name":"Area-Language Design","color":"5319e7"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Feature%20Request","name":"Feature Request","color":"fc2929"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Language-C%23","name":"Language-C#","color":"207de5"}],"state":"open","locked":false,"assignee":{"login":"MadsTorgersen","id":6677272,"avatar_url":"https://avatars.githubusercontent.com/u/6677272?v=3","gravatar_id":"","url":"https://api.github.com/users/MadsTorgersen","html_url":"https://github.com/MadsTorgersen","followers_url":"https://api.github.com/users/MadsTorgersen/followers","following_url":"https://api.github.com/users/MadsTorgersen/following{/other_user}","gists_url":"https://api.github.com/users/MadsTorgersen/gists{/gist_id}","starred_url":"https://api.github.com/users/MadsTorgersen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MadsTorgersen/subscriptions","organizations_url":"https://api.github.com/users/MadsTorgersen/orgs","repos_url":"https://api.github.com/users/MadsTorgersen/repos","events_url":"https://api.github.com/users/MadsTorgersen/events{/privacy}","received_events_url":"https://api.github.com/users/MadsTorgersen/received_events","type":"User","site_admin":false},"milestone":null,"comments":36,"created_at":"2015-01-28T18:03:25Z","updated_at":"2015-09-09T11:15:33Z","closed_at":null,"body":"(Note: this proposal was briefly discussed in #98, the C# design notes for Jan 21, 2015. It has not been updated based on the discussion that's already occurred on that thread.)\r\n\r\n## Background\r\nSince the first release of C#, the language has supported passing parameters by reference using the 'ref' keyword, This is built on top of direct support in the runtime for passing parameters by reference. \r\n\r\n## Problem\r\nInterestingly, that support in the CLR is actually a more general mechanism for passing around safe references to heap memory and stack locations; that could be used to implement support for ref return values and ref locals, but C# historically has not provided any mechanism for doing this in safe code.  Instead, developers that want to pass around structured blocks of memory are often forced to do so with pointers to pinned memory, which is both unsafe and often inefficient.\r\n\r\n## Solution: ref returns\r\nThe language should support the ability to declare ref locals and ref return values.  We could, for example, now declare a function like the following, which not only accepts 'ref' parameters but which also has a ref return value:\r\n```C#\r\npublic static ref TValue Choose<TValue>(\r\n    Func<bool> condition, ref TValue left, ref TValue right)\r\n{\r\n    return condition() ? ref left : ref right;\r\n}\r\n```\r\nWith a method like that, one can now write code that passes two values by reference, with one of them being returned based on some condition:\r\n```C#\r\nMatrix3D left = …, right = …;\r\nChoose(chooser, ref left, ref right).M20 = 1.0;\r\n```\r\nBased on the function that gets passed in here, a reference to either 'left' or 'right' will be returned, and the M20 field of it will be set.  Since we’re trading in references, the value contained in either 'left' or 'right' is updated, rather than a temporary copy being updated, and rather than needing to pass around big structures, necessitating big copies.\r\n\r\nIf we don't want the returned reference to be writable, we could apply 'readonly' just as we were able to do earlier with ‘ref’ on parameters (extending the proposal mentioned in #115 to also support return refs):\r\n```C#\r\npublic static readonly ref TValue Choose<TValue>(\r\n    Func<bool> condition, ref TValue left, ref TValue right)\r\n{\r\n    return condition() ? ref left : ref right;\r\n}\r\n…\r\nMatrix3D left = …, right = …;\r\nChoose(chooser, ref left, ref right) = new Matrix3D(...); // Error: returned reference is read-only\r\n```\r\nNote that when referencing the 'left' and 'right' ref arguments in the Choose method’s implementation, we used the 'ref' keyword.  This would be required by the language, just as it’s required to use the ‘ref’ keyword when passing a value to a 'ref' parameter.\r\n\r\n## Solution: ref locals\r\nOnce you have the ability to receive 'ref' parameters and to return ‘ref’ return values, it’s very handy to be able to define 'ref' locals as well.  A 'ref' local can be set to anything that’s safe to return as a 'ref' return, which includes references to variables on the heap, 'ref' parameters, 'ref' values returned from a call to another method where all 'ref' arguments to that method were safe to return, and other 'ref' locals.\r\n```C#\r\npublic static ref int Max(ref int first, ref int second, ref int third)\r\n{\r\n    ref int max = first > second ? ref first : ref second;\r\n    return max > third ? ref max : ref third;\r\n}\r\n…\r\nint a = 1, b = 2, c = 3;\r\nMax(ref a, ref b, ref c) = 4;\r\nDebug.Assert(a == 1); // true\r\nDebug.Assert(b == 2); // true\r\nDebug.Assert(c == 4); // true\r\n```    \r\nWe could also use ‘readonly’ with ref on locals (again, see #115), to ensure that the ref variables don’t change.  This would work not only with ref parameters, but also with ref locals and ref returns:\r\n```C#\r\npublic static readonly ref int Max(\r\n    readonly ref int first, readonly ref int second, readonly ref int third)\r\n{\r\n    readonly ref int max = first > second ? ref first : ref second;\r\n    return max > third ? ref max : ref third;\r\n}\r\n```\r\n\r\n\r\n<!---\r\n@huboard:{\"order\":18.0}\r\n-->\r\n"},"comment":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/comments/138878517","html_url":"https://github.com/dotnet/roslyn/issues/118#issuecomment-138878517","issue_url":"https://api.github.com/repos/dotnet/roslyn/issues/118","id":138878517,"user":{"login":"HaloFour","id":10102290,"avatar_url":"https://avatars.githubusercontent.com/u/10102290?v=3","gravatar_id":"","url":"https://api.github.com/users/HaloFour","html_url":"https://github.com/HaloFour","followers_url":"https://api.github.com/users/HaloFour/followers","following_url":"https://api.github.com/users/HaloFour/following{/other_user}","gists_url":"https://api.github.com/users/HaloFour/gists{/gist_id}","starred_url":"https://api.github.com/users/HaloFour/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HaloFour/subscriptions","organizations_url":"https://api.github.com/users/HaloFour/orgs","repos_url":"https://api.github.com/users/HaloFour/repos","events_url":"https://api.github.com/users/HaloFour/events{/privacy}","received_events_url":"https://api.github.com/users/HaloFour/received_events","type":"User","site_admin":false},"created_at":"2015-09-09T11:15:33Z","updated_at":"2015-09-09T11:15:33Z","body":"@axel-habermaier Maybe.  That wouldn't be my first guess given the proposal they posted under, but it is terribly unspecific.  IIRC `ref` parameter capture would be wading too close to `unsafe` territory since you'd basically have to stuff the address to a variable in the state machine class and the compiler could no longer control its lifetime.\r\n\r\n@Thaina C# has always supported `ref` and `out` parameters for anonymous delegates and lambdas."}}