{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/csharplang/issues/505","repository_url":"https://api.github.com/repos/dotnet/csharplang","labels_url":"https://api.github.com/repos/dotnet/csharplang/issues/505/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/csharplang/issues/505/comments","events_url":"https://api.github.com/repos/dotnet/csharplang/issues/505/events","html_url":"https://github.com/dotnet/csharplang/issues/505","id":224722883,"number":505,"title":"Null-conditional operator `??` not allowed in generics unless constraint with `class`","user":{"login":"lachbaer","id":17041498,"avatar_url":"https://avatars3.githubusercontent.com/u/17041498?v=3","gravatar_id":"","url":"https://api.github.com/users/lachbaer","html_url":"https://github.com/lachbaer","followers_url":"https://api.github.com/users/lachbaer/followers","following_url":"https://api.github.com/users/lachbaer/following{/other_user}","gists_url":"https://api.github.com/users/lachbaer/gists{/gist_id}","starred_url":"https://api.github.com/users/lachbaer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lachbaer/subscriptions","organizations_url":"https://api.github.com/users/lachbaer/orgs","repos_url":"https://api.github.com/users/lachbaer/repos","events_url":"https://api.github.com/users/lachbaer/events{/privacy}","received_events_url":"https://api.github.com/users/lachbaer/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":7,"created_at":"2017-04-27T09:20:18Z","updated_at":"2017-04-27T17:48:20Z","closed_at":null,"body":"I encountered a curiosity. Given the following code:\r\n```cs\r\npublic int TheFunction<T>(T a, T b)\r\n{\r\n    T c;\r\n    c = (a != null) ? a : b;\r\n    \r\n    T d;\r\n    d = a ?? b; // CS0019  Operator '??' cannot be applied to operands of type 'T' and 'T'\r\n\r\n    var hash = c?.GetHashCode();\r\n    return hash ?? 0;\r\n}\r\n\r\npublic static void Test()\r\n{\r\n    ValueGeneric testObj = new ValueGeneric();\r\n    int a = 1234;\r\n    int b = 2345;\r\n    int c;\r\n    int? an = null;\r\n    int? bn = null;\r\n    c = testObj.TheFunction(a, b);\r\n    c = testObj.TheFunction(an, bn);\r\n}\r\n```\r\nThe occurence of the `??` operator causes an error, though its equivalent replacement with `a != null` compiles. The explicit condition works with value types for 'T' also. 'a' is converted to `T?` implicitly for that condition.\r\n\r\nWhen constraining with 'where T : class' the error does not occur. When constraining with 'where T : new()' it arises again, ~though value types currently cannot be 'T : new()' what implies 'T' being a 'class' as the only alternative~.\r\n\r\nEven when changing the declartion to `T? d` it still produces that error, though 'a' and 'b' could be implicitly converted to the result type.\r\n\r\nThe problem probably arises from the specs that defines all the possible conversions for `??` and that doesn't allow this operator on non-nullable value types currently.\r\n\r\nShall the specs be extended to support `U = T ?? W` \r\n* with 'T, U, W' all being value types\r\n* implicit conversions 'T=>U',  'W=>U' and 'W=>T' exist\r\n* in that case always expression 'T' results (because 'T' as a value-type is always non-null)\r\n\r\nIs it possible that in case 'T' is not a generic type, a warning or error is issued?\r\n\r\nThis will break nothing, because there currently cannot be existing code that makes use of it.\r\n"},"comment":{"url":"https://api.github.com/repos/dotnet/csharplang/issues/comments/297788947","html_url":"https://github.com/dotnet/csharplang/issues/505#issuecomment-297788947","issue_url":"https://api.github.com/repos/dotnet/csharplang/issues/505","id":297788947,"user":{"login":"lachbaer","id":17041498,"avatar_url":"https://avatars3.githubusercontent.com/u/17041498?v=3","gravatar_id":"","url":"https://api.github.com/users/lachbaer","html_url":"https://github.com/lachbaer","followers_url":"https://api.github.com/users/lachbaer/followers","following_url":"https://api.github.com/users/lachbaer/following{/other_user}","gists_url":"https://api.github.com/users/lachbaer/gists{/gist_id}","starred_url":"https://api.github.com/users/lachbaer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lachbaer/subscriptions","organizations_url":"https://api.github.com/users/lachbaer/orgs","repos_url":"https://api.github.com/users/lachbaer/repos","events_url":"https://api.github.com/users/lachbaer/events{/privacy}","received_events_url":"https://api.github.com/users/lachbaer/received_events","type":"User","site_admin":false},"created_at":"2017-04-27T17:48:20Z","updated_at":"2017-04-27T17:48:20Z","body":"@CyrusNajmabadi You nicely explain why it currently is so and what could be done to circumvent this issue. FYI, I alread knew this ;-) This issue is rather about whether it would make sense to extend the specs.\r\n\r\n>> Shall the specs be extended to support U = T ?? W\r\nwith 'T, U, W' all being value types\r\n\r\n> I'm not sure how that would make sense. If T was a value type here, it would never be null. so this would just be equivalent to \"U = T\".\r\n\r\nThat would be the outcome, yes. But I'm asking in favor for **generics** primarily. As @jnm2 will perhaps concur, the null-coalescing operator is primarily perceived as being a synonym for `x != null ? x : y`. (If you believe that is only my view on things, then I'd be happy to start a poll 😉 )\r\n"}}
{"actor":{"display_login":"lachbaer"}}