{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/corefx/issues/14507","repository_url":"https://api.github.com/repos/dotnet/corefx","labels_url":"https://api.github.com/repos/dotnet/corefx/issues/14507/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/corefx/issues/14507/comments","events_url":"https://api.github.com/repos/dotnet/corefx/issues/14507/events","html_url":"https://github.com/dotnet/corefx/issues/14507","id":195492700,"number":14507,"title":"Span: Create Span from IntPtr","user":{"login":"ektrah","id":4752078,"avatar_url":"https://avatars.githubusercontent.com/u/4752078?v=3","gravatar_id":"","url":"https://api.github.com/users/ektrah","html_url":"https://github.com/ektrah","followers_url":"https://api.github.com/users/ektrah/followers","following_url":"https://api.github.com/users/ektrah/following{/other_user}","gists_url":"https://api.github.com/users/ektrah/gists{/gist_id}","starred_url":"https://api.github.com/users/ektrah/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ektrah/subscriptions","organizations_url":"https://api.github.com/users/ektrah/orgs","repos_url":"https://api.github.com/users/ektrah/repos","events_url":"https://api.github.com/users/ektrah/events{/privacy}","received_events_url":"https://api.github.com/users/ektrah/received_events","type":"User","site_admin":false},"labels":[{"id":153714228,"url":"https://api.github.com/repos/dotnet/corefx/labels/api-needs-work","name":"api-needs-work","color":"207de5","default":false},{"id":174276033,"url":"https://api.github.com/repos/dotnet/corefx/labels/area-System.Runtime","name":"area-System.Runtime","color":"d4c5f9","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2016-12-14T10:23:20Z","updated_at":"2016-12-15T04:06:18Z","closed_at":null,"body":"(ReadOnly)Span\\<T> is designed so that it can point to native memory. So far, native memory is typically represented by a SafeHandle (e.g., SafeMemoryMappedViewHandle) or an IntPtr (e.g., as returned by Marshal.AllocHGlobal). It will probably a common use case to create a (ReadOnly)Span\\<byte> from these.\r\n\r\n*Proposal:*\r\n\r\nAdd a constructor overload that accepts an IntPtr and a length:\r\n\r\n```diff\r\n  public struct Span<T>\r\n  {\r\n+     public Span(IntPtr pointer, int length) { ... }\r\n\r\n  public struct ReadOnlySpan<T>\r\n  {\r\n+     public ReadOnlySpan(IntPtr pointer, int length) { ... }\r\n```\r\n\r\n*Example Usage 1:*\r\n\r\n```csharp\r\nint length = 4096;\r\nSafeHandle handle = VirtualAlloc(IntPtr.Zero, new IntPtr(length), 0x3000, 0x04);\r\n\r\nbool addedRef = false;\r\ntry\r\n{\r\n    handle.DangerousAddRef(ref addedRef);\r\n    MyMethod(new Span<byte>(handle.DangerousGetHandle(), length));\r\n}\r\nfinally\r\n{\r\n    if (addedRef)\r\n    {\r\n        handle.DangerousRelease();\r\n    }\r\n}\r\n```\r\n\r\n*Example Usage 2:*\r\n\r\n```csharp\r\nint length = 512;\r\n\r\nIntPtr hglobal = Marshal.AllocHGlobal(length);\r\ntry\r\n{\r\n    MyMethod(new Span<byte>(hglobal, length));\r\n}\r\nfinally\r\n{\r\n    Marshal.FreeHGlobal(hglobal);\r\n}\r\n```\r\n\r\nThere is currently a constructor overload that accepts a void* and a length, and an IntPtr can of course easily be converted to a void* using the IntPtr.ToPointer method. However, this requires `<AllowUnsafeBlocks>true</AllowUnsafeBlocks>` and is the only instance in the API surface where an `unsafe` code block is required. It would be nice if spans could be used without `unsafe` code blocks. IMHO requiring `unsafe` when working with native memory doesn't really make things safer since there are already methods like Marshal.ReadInt32 that can be used to read or write arbitrary native memory through an IntPtr."},"comment":{"url":"https://api.github.com/repos/dotnet/corefx/issues/comments/267233574","html_url":"https://github.com/dotnet/corefx/issues/14507#issuecomment-267233574","issue_url":"https://api.github.com/repos/dotnet/corefx/issues/14507","id":267233574,"user":{"login":"morganbr","id":11641665,"avatar_url":"https://avatars.githubusercontent.com/u/11641665?v=3","gravatar_id":"","url":"https://api.github.com/users/morganbr","html_url":"https://github.com/morganbr","followers_url":"https://api.github.com/users/morganbr/followers","following_url":"https://api.github.com/users/morganbr/following{/other_user}","gists_url":"https://api.github.com/users/morganbr/gists{/gist_id}","starred_url":"https://api.github.com/users/morganbr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/morganbr/subscriptions","organizations_url":"https://api.github.com/users/morganbr/orgs","repos_url":"https://api.github.com/users/morganbr/repos","events_url":"https://api.github.com/users/morganbr/events{/privacy}","received_events_url":"https://api.github.com/users/morganbr/received_events","type":"User","site_admin":false},"created_at":"2016-12-15T04:06:18Z","updated_at":"2016-12-15T04:06:18Z","body":"Having direct handling for SafeHandles might also be good so users don't need to get the DangerousAddRef/DangerousReleaseRef pattern in example 1 correct. I wonder if it's even worth having Span's lifetime semantics keep the SafeHandle alive correctly."}}
{"actor":{"display_login":"morganbr"}}