{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/csharplang/issues/829","repository_url":"https://api.github.com/repos/dotnet/csharplang","labels_url":"https://api.github.com/repos/dotnet/csharplang/issues/829/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/csharplang/issues/829/comments","events_url":"https://api.github.com/repos/dotnet/csharplang/issues/829/events","html_url":"https://github.com/dotnet/csharplang/issues/829","id":250939481,"number":829,"title":"Proposal: extend tuple projection initializers to preserving element names through unnamed tuples","user":{"login":"DavidArno","id":196899,"avatar_url":"https://avatars3.githubusercontent.com/u/196899?v=4","gravatar_id":"","url":"https://api.github.com/users/DavidArno","html_url":"https://github.com/DavidArno","followers_url":"https://api.github.com/users/DavidArno/followers","following_url":"https://api.github.com/users/DavidArno/following{/other_user}","gists_url":"https://api.github.com/users/DavidArno/gists{/gist_id}","starred_url":"https://api.github.com/users/DavidArno/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DavidArno/subscriptions","organizations_url":"https://api.github.com/users/DavidArno/orgs","repos_url":"https://api.github.com/users/DavidArno/repos","events_url":"https://api.github.com/users/DavidArno/events{/privacy}","received_events_url":"https://api.github.com/users/DavidArno/received_events","type":"User","site_admin":false},"labels":[{"id":537024200,"url":"https://api.github.com/repos/dotnet/csharplang/labels/Discussion","name":"Discussion","color":"c2e0c6","default":false},{"id":545773793,"url":"https://api.github.com/repos/dotnet/csharplang/labels/Feature%20Request","name":"Feature Request","color":"d4c5f9","default":false}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":11,"created_at":"2017-08-17T13:13:56Z","updated_at":"2017-08-20T18:55:53Z","closed_at":"2017-08-20T18:19:04Z","body":"(This proposal is a rewording of a comment from [#415](https://github.com/dotnet/csharplang/issues/415#issuecomment-321265036))\r\n\r\nCurrently, as of v7.1, the compiler can \"project\" tuple names across expressions. However, this \"breaks down\" the moment a tuple with unnamed elements is introduced. For example, the following code won't compile:\r\n```cs\r\n(T1, T2) Bar<T1, T2>() => (a:default, b:default);\r\n\r\nvar x = Bar<int, int>();\r\nvar y = x.a; // Bar returns (int, int), not (int a, int b), so a cannot be accessed.\r\n```\r\n\r\nThere is a use case where being able to preserve names across a tuple with unnamed elements \"boundary\" and that is when method chaining with methods that take a generic tuple as a parameter.\r\n\r\nThis can be explained without using a complex method chaining example with the following simple code example:\r\n```cs\r\npublic static void Foo()\r\n{\r\n    (T1, T2) Bar<T1, T2>((T1, T2) value) => value;\r\n\r\n    var tuple = (a:1, b:2);\r\n    var newTuple = Bar(tuple);\r\n    var a = newTuple.a; // Since we passed (a, b) in, it would be extremely useful to \r\n                        // get (a, b) back out again\r\n}\r\n```\r\n\r\nAs `ValueTuple<T1, T2>` is a `struct`, it isn't possible to just use `Bar<T>` and constrain `T` using generic constraints. The only current solution is to use an unconstrained `T`, but then the method can't be constrained to a tuple and the elements are not accessible from within `Bar`. \r\n\r\n**UPDATE**\r\n\r\nTo give a possibly clearer example, take the following extension method for `(T1, T2)`:\r\n```cs\r\npublic static TR Foo<T1, T2, TR>(this (T1, T2) t, Func<(T1, T2), TR> f) => f(t);\r\n\r\n...\r\n\r\n(a:1, b:1).Foo(t => t.a == t.b); // doesn't compile as the compiler doesn't \"project\" \r\n                                 // a & b through the (T1, T2) type declaration\r\n```\r\n"},"comment":{"url":"https://api.github.com/repos/dotnet/csharplang/issues/comments/323604335","html_url":"https://github.com/dotnet/csharplang/issues/829#issuecomment-323604335","issue_url":"https://api.github.com/repos/dotnet/csharplang/issues/829","id":323604335,"user":{"login":"DavidArno","id":196899,"avatar_url":"https://avatars3.githubusercontent.com/u/196899?v=4","gravatar_id":"","url":"https://api.github.com/users/DavidArno","html_url":"https://github.com/DavidArno","followers_url":"https://api.github.com/users/DavidArno/followers","following_url":"https://api.github.com/users/DavidArno/following{/other_user}","gists_url":"https://api.github.com/users/DavidArno/gists{/gist_id}","starred_url":"https://api.github.com/users/DavidArno/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DavidArno/subscriptions","organizations_url":"https://api.github.com/users/DavidArno/orgs","repos_url":"https://api.github.com/users/DavidArno/repos","events_url":"https://api.github.com/users/DavidArno/events{/privacy}","received_events_url":"https://api.github.com/users/DavidArno/received_events","type":"User","site_admin":false},"created_at":"2017-08-20T18:55:53Z","updated_at":"2017-08-20T18:55:53Z","body":"@eyalsk,\r\n\r\nI get that. Where my head is at the moment, tuples are the single most important feature added to v7.0. They were enhanced by v7.1. But the inability of the language/compiler to grasp that tuple A is the same tuple as tuple B, when passed across an \"opaque boundary\" severely limits their use. But I accept that no one else gets that/accepts the need for that. So I've closed this.\r\n\r\nMaybe in future, others will see the need. Or maybe I'll remain unique in wanting to use them this way. Time will tell."}}
{"actor":{"display_login":"DavidArno"}}