{"action":"opened","issue":{"url":"https://api.github.com/repos/dotnet/csharplang/issues/1790","repository_url":"https://api.github.com/repos/dotnet/csharplang","labels_url":"https://api.github.com/repos/dotnet/csharplang/issues/1790/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/csharplang/issues/1790/comments","events_url":"https://api.github.com/repos/dotnet/csharplang/issues/1790/events","html_url":"https://github.com/dotnet/csharplang/issues/1790","id":351442368,"node_id":"MDU6SXNzdWUzNTE0NDIzNjg=","number":1790,"title":"Proposal: readonly and sealed interfaces","user":{"login":"leonidumanskiy","id":7004323,"node_id":"MDQ6VXNlcjcwMDQzMjM=","avatar_url":"https://avatars0.githubusercontent.com/u/7004323?v=4","gravatar_id":"","url":"https://api.github.com/users/leonidumanskiy","html_url":"https://github.com/leonidumanskiy","followers_url":"https://api.github.com/users/leonidumanskiy/followers","following_url":"https://api.github.com/users/leonidumanskiy/following{/other_user}","gists_url":"https://api.github.com/users/leonidumanskiy/gists{/gist_id}","starred_url":"https://api.github.com/users/leonidumanskiy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leonidumanskiy/subscriptions","organizations_url":"https://api.github.com/users/leonidumanskiy/orgs","repos_url":"https://api.github.com/users/leonidumanskiy/repos","events_url":"https://api.github.com/users/leonidumanskiy/events{/privacy}","received_events_url":"https://api.github.com/users/leonidumanskiy/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-08-17T03:13:06Z","updated_at":"2018-08-17T03:13:06Z","closed_at":null,"author_association":"NONE","body":"**Quick summary**\r\nIntroduce new usage for keywords \"readonly\" and \"sealed\":\r\n```c#\r\n// Interface can not be inherited\r\npublic sealed interface IService { } \r\n```\r\n\r\n```c#\r\n// Interface can only be implemented within current assembly\r\npublic readonly interface IService { } \r\n```\r\n\r\n**Motivation**\r\n- Prevent consumers of your library/nuget package from re-implementing your interfaces. \r\n- Guarantee that adding new methods to existing interfaces will **not** break existing consumer code.\r\n- Classes already have that mechanism (make all constructors private/internal). There is no such mechanism for interfaces.\r\n\r\n**Motivation (longer explanation)**\r\nWhen declaring an interface within a library, one could have two possible intentions:\r\n1. Interface is intended to be implemented by library/package consumers. Adding new methods to that interface is considered a breaking change.\r\n2. Interface is implemented within the library and it is not intended for client to re-implement it. When new methods are added to that interface, it is not considered a breaking change.\r\n\r\nUnfortunately, there is no way to make it clear whether consumers should or should not implement a given interface. As a result, it is not possible to add new methods to interfaces and guarantee that updating the library will not break consumer code.\r\n\r\nAs a result, when it comes to selecting a versioning strategy for your library you have two options:\r\n1. Consider every interface change a breaking change. Increment a major version of your library / nuget package every time you add new functionality to an interface.\r\n2. Rely on the documentation to describe what interfaces are not intended to be implemented by consumers. When adding new methods to your interfaces, consider it non-breaking change and only increment minor version.\r\n"}}
{"actor":{"display_login":"leonidumanskiy"}}