Can I get a pointer to a Span?












1















I have a (ReadOnly)Span<byte> from which I want to decode a string.



Only in .NET Core 2.1 I have the new overload to decode a string from it without needing to copy the bytes:



Encoding.GetString(ReadOnlySpan<byte> bytes);


In .NET Standard 2.0 and .NET 4.6 (which I also want to support), I only have the classic overloads:



Encoding.GetString(byte bytes);
Encoding.GetString(byte* bytes, int byteCount);


The first one requires a copy of the bytes into an array which I want to avoid.

The second requires a byte pointer, so I thought about getting one from my span, like



Encoding.GetString(Unsafe.GetPointer<byte>(span.Slice(100)))


...but I failed finding an actual method for that. I tried void* Unsafe.AsPointer<T>(ref T value), but I cannot pass a span to that, and didn't find another method dealing with pointers (and spans).



Is this possible at all, and if yes, how?










share|improve this question




















  • 1





    Enter [ReadOnly]Span<T>.GetPinnableReference(). If using C# 7.3, leveraging this is as simple as fixed (byte* bytes = span) -- this compiles for .NET 4.5.2, at least, I haven't tested if it will also really work (I only have later frameworks installed).

    – Jeroen Mostert
    Jan 18 at 14:43













  • In prior C# versions, you can use the return value of ref GetPinnableReference() as the argument to Unsafe.AsPointer. You need at least C# 7.0 to use ref locals.

    – Jeroen Mostert
    Jan 18 at 14:49











  • @JeroenMostert This is great, I'm using C# 7.3 and it's working smooth as silk. Do you want to post an answer about it so I can accept it?

    – Ray Koopa
    Jan 18 at 16:04











  • With the help of ILSpy, I actually found a more convenient syntax for earlier versions as well. Also not tested, but since the pointers returned are identical I'm going to assume it works.

    – Jeroen Mostert
    Jan 18 at 16:16
















1















I have a (ReadOnly)Span<byte> from which I want to decode a string.



Only in .NET Core 2.1 I have the new overload to decode a string from it without needing to copy the bytes:



Encoding.GetString(ReadOnlySpan<byte> bytes);


In .NET Standard 2.0 and .NET 4.6 (which I also want to support), I only have the classic overloads:



Encoding.GetString(byte bytes);
Encoding.GetString(byte* bytes, int byteCount);


The first one requires a copy of the bytes into an array which I want to avoid.

The second requires a byte pointer, so I thought about getting one from my span, like



Encoding.GetString(Unsafe.GetPointer<byte>(span.Slice(100)))


...but I failed finding an actual method for that. I tried void* Unsafe.AsPointer<T>(ref T value), but I cannot pass a span to that, and didn't find another method dealing with pointers (and spans).



Is this possible at all, and if yes, how?










share|improve this question




















  • 1





    Enter [ReadOnly]Span<T>.GetPinnableReference(). If using C# 7.3, leveraging this is as simple as fixed (byte* bytes = span) -- this compiles for .NET 4.5.2, at least, I haven't tested if it will also really work (I only have later frameworks installed).

    – Jeroen Mostert
    Jan 18 at 14:43













  • In prior C# versions, you can use the return value of ref GetPinnableReference() as the argument to Unsafe.AsPointer. You need at least C# 7.0 to use ref locals.

    – Jeroen Mostert
    Jan 18 at 14:49











  • @JeroenMostert This is great, I'm using C# 7.3 and it's working smooth as silk. Do you want to post an answer about it so I can accept it?

    – Ray Koopa
    Jan 18 at 16:04











  • With the help of ILSpy, I actually found a more convenient syntax for earlier versions as well. Also not tested, but since the pointers returned are identical I'm going to assume it works.

    – Jeroen Mostert
    Jan 18 at 16:16














1












1








1








I have a (ReadOnly)Span<byte> from which I want to decode a string.



Only in .NET Core 2.1 I have the new overload to decode a string from it without needing to copy the bytes:



Encoding.GetString(ReadOnlySpan<byte> bytes);


In .NET Standard 2.0 and .NET 4.6 (which I also want to support), I only have the classic overloads:



Encoding.GetString(byte bytes);
Encoding.GetString(byte* bytes, int byteCount);


The first one requires a copy of the bytes into an array which I want to avoid.

The second requires a byte pointer, so I thought about getting one from my span, like



Encoding.GetString(Unsafe.GetPointer<byte>(span.Slice(100)))


...but I failed finding an actual method for that. I tried void* Unsafe.AsPointer<T>(ref T value), but I cannot pass a span to that, and didn't find another method dealing with pointers (and spans).



Is this possible at all, and if yes, how?










share|improve this question
















I have a (ReadOnly)Span<byte> from which I want to decode a string.



Only in .NET Core 2.1 I have the new overload to decode a string from it without needing to copy the bytes:



Encoding.GetString(ReadOnlySpan<byte> bytes);


In .NET Standard 2.0 and .NET 4.6 (which I also want to support), I only have the classic overloads:



Encoding.GetString(byte bytes);
Encoding.GetString(byte* bytes, int byteCount);


The first one requires a copy of the bytes into an array which I want to avoid.

The second requires a byte pointer, so I thought about getting one from my span, like



Encoding.GetString(Unsafe.GetPointer<byte>(span.Slice(100)))


...but I failed finding an actual method for that. I tried void* Unsafe.AsPointer<T>(ref T value), but I cannot pass a span to that, and didn't find another method dealing with pointers (and spans).



Is this possible at all, and if yes, how?







c# .net-standard-2.0 .net-4.6 .net-core-2.1






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 18 at 16:06







Ray Koopa

















asked Jan 18 at 14:19









Ray KoopaRay Koopa

2,69722858




2,69722858








  • 1





    Enter [ReadOnly]Span<T>.GetPinnableReference(). If using C# 7.3, leveraging this is as simple as fixed (byte* bytes = span) -- this compiles for .NET 4.5.2, at least, I haven't tested if it will also really work (I only have later frameworks installed).

    – Jeroen Mostert
    Jan 18 at 14:43













  • In prior C# versions, you can use the return value of ref GetPinnableReference() as the argument to Unsafe.AsPointer. You need at least C# 7.0 to use ref locals.

    – Jeroen Mostert
    Jan 18 at 14:49











  • @JeroenMostert This is great, I'm using C# 7.3 and it's working smooth as silk. Do you want to post an answer about it so I can accept it?

    – Ray Koopa
    Jan 18 at 16:04











  • With the help of ILSpy, I actually found a more convenient syntax for earlier versions as well. Also not tested, but since the pointers returned are identical I'm going to assume it works.

    – Jeroen Mostert
    Jan 18 at 16:16














  • 1





    Enter [ReadOnly]Span<T>.GetPinnableReference(). If using C# 7.3, leveraging this is as simple as fixed (byte* bytes = span) -- this compiles for .NET 4.5.2, at least, I haven't tested if it will also really work (I only have later frameworks installed).

    – Jeroen Mostert
    Jan 18 at 14:43













  • In prior C# versions, you can use the return value of ref GetPinnableReference() as the argument to Unsafe.AsPointer. You need at least C# 7.0 to use ref locals.

    – Jeroen Mostert
    Jan 18 at 14:49











  • @JeroenMostert This is great, I'm using C# 7.3 and it's working smooth as silk. Do you want to post an answer about it so I can accept it?

    – Ray Koopa
    Jan 18 at 16:04











  • With the help of ILSpy, I actually found a more convenient syntax for earlier versions as well. Also not tested, but since the pointers returned are identical I'm going to assume it works.

    – Jeroen Mostert
    Jan 18 at 16:16








1




1





Enter [ReadOnly]Span<T>.GetPinnableReference(). If using C# 7.3, leveraging this is as simple as fixed (byte* bytes = span) -- this compiles for .NET 4.5.2, at least, I haven't tested if it will also really work (I only have later frameworks installed).

– Jeroen Mostert
Jan 18 at 14:43







Enter [ReadOnly]Span<T>.GetPinnableReference(). If using C# 7.3, leveraging this is as simple as fixed (byte* bytes = span) -- this compiles for .NET 4.5.2, at least, I haven't tested if it will also really work (I only have later frameworks installed).

– Jeroen Mostert
Jan 18 at 14:43















In prior C# versions, you can use the return value of ref GetPinnableReference() as the argument to Unsafe.AsPointer. You need at least C# 7.0 to use ref locals.

– Jeroen Mostert
Jan 18 at 14:49





In prior C# versions, you can use the return value of ref GetPinnableReference() as the argument to Unsafe.AsPointer. You need at least C# 7.0 to use ref locals.

– Jeroen Mostert
Jan 18 at 14:49













@JeroenMostert This is great, I'm using C# 7.3 and it's working smooth as silk. Do you want to post an answer about it so I can accept it?

– Ray Koopa
Jan 18 at 16:04





@JeroenMostert This is great, I'm using C# 7.3 and it's working smooth as silk. Do you want to post an answer about it so I can accept it?

– Ray Koopa
Jan 18 at 16:04













With the help of ILSpy, I actually found a more convenient syntax for earlier versions as well. Also not tested, but since the pointers returned are identical I'm going to assume it works.

– Jeroen Mostert
Jan 18 at 16:16





With the help of ILSpy, I actually found a more convenient syntax for earlier versions as well. Also not tested, but since the pointers returned are identical I'm going to assume it works.

– Jeroen Mostert
Jan 18 at 16:16












2 Answers
2






active

oldest

votes


















3














If you have C# 7.3 or later, you can use the extension made to the fixed statement that can use any appropriate GetPinnableReference method on a type (which Span and ReadOnlySpan have):



fixed (byte* bp = bytes) {
...
}


As we're dealing with pointers this requires an unsafe context, of course.



C# 7.0 through 7.2 don't have this, but allow the following:



fixed (byte* bp = &bytes.GetPinnableReference()) {
...
}





share|improve this answer
























  • Pretty cool. I accept this as an answer as it also covers new C# 7.3 syntax.

    – Ray Koopa
    Jan 18 at 16:18



















2














Try this:



Span<byte> bytes = ...;
string s = Encoding.UTF8.GetString((byte*)Unsafe.AsPointer(ref bytes.GetPinnableReference()),
bytes.Length);





share|improve this answer


























  • Thanks! I did not see GetPinnableReference() anywhere in IntelliSense. However, this did not seem to work for ReadOnlySpan<byte> (it cannot pass it as ref because it is readonly); but it would work for my initial question (only now I realized I have a ReadOnlySpan, sorry!).

    – Ray Koopa
    Jan 18 at 16:00











  • @RayKoopa: the reason you couldn't see the method, by the way, is because it was explicitly hidden as feature. This was back when it was called DangerousGetPinnableReference; it's since been downgraded to "not actually that dangerous", but the method's still hidden.

    – Jeroen Mostert
    Jan 18 at 16:21






  • 1





    The alternative proposed for ReadOnlySpan is not correct! Storing it in a variable first and taking the ref of that gives you a reference to the local byte, not the spanned array. Accessing any element beyond the first this way will give garbage.

    – Jeroen Mostert
    Jan 18 at 16:25











  • @JeroenMostert I actually remember that "Dangerous" method name. I didn't follow up on the recent changes, thanks for clearing this up.

    – Ray Koopa
    Jan 18 at 16:28











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54255888%2fcan-i-get-a-pointer-to-a-span%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














If you have C# 7.3 or later, you can use the extension made to the fixed statement that can use any appropriate GetPinnableReference method on a type (which Span and ReadOnlySpan have):



fixed (byte* bp = bytes) {
...
}


As we're dealing with pointers this requires an unsafe context, of course.



C# 7.0 through 7.2 don't have this, but allow the following:



fixed (byte* bp = &bytes.GetPinnableReference()) {
...
}





share|improve this answer
























  • Pretty cool. I accept this as an answer as it also covers new C# 7.3 syntax.

    – Ray Koopa
    Jan 18 at 16:18
















3














If you have C# 7.3 or later, you can use the extension made to the fixed statement that can use any appropriate GetPinnableReference method on a type (which Span and ReadOnlySpan have):



fixed (byte* bp = bytes) {
...
}


As we're dealing with pointers this requires an unsafe context, of course.



C# 7.0 through 7.2 don't have this, but allow the following:



fixed (byte* bp = &bytes.GetPinnableReference()) {
...
}





share|improve this answer
























  • Pretty cool. I accept this as an answer as it also covers new C# 7.3 syntax.

    – Ray Koopa
    Jan 18 at 16:18














3












3








3







If you have C# 7.3 or later, you can use the extension made to the fixed statement that can use any appropriate GetPinnableReference method on a type (which Span and ReadOnlySpan have):



fixed (byte* bp = bytes) {
...
}


As we're dealing with pointers this requires an unsafe context, of course.



C# 7.0 through 7.2 don't have this, but allow the following:



fixed (byte* bp = &bytes.GetPinnableReference()) {
...
}





share|improve this answer













If you have C# 7.3 or later, you can use the extension made to the fixed statement that can use any appropriate GetPinnableReference method on a type (which Span and ReadOnlySpan have):



fixed (byte* bp = bytes) {
...
}


As we're dealing with pointers this requires an unsafe context, of course.



C# 7.0 through 7.2 don't have this, but allow the following:



fixed (byte* bp = &bytes.GetPinnableReference()) {
...
}






share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 18 at 16:15









Jeroen MostertJeroen Mostert

17.4k2252




17.4k2252













  • Pretty cool. I accept this as an answer as it also covers new C# 7.3 syntax.

    – Ray Koopa
    Jan 18 at 16:18



















  • Pretty cool. I accept this as an answer as it also covers new C# 7.3 syntax.

    – Ray Koopa
    Jan 18 at 16:18

















Pretty cool. I accept this as an answer as it also covers new C# 7.3 syntax.

– Ray Koopa
Jan 18 at 16:18





Pretty cool. I accept this as an answer as it also covers new C# 7.3 syntax.

– Ray Koopa
Jan 18 at 16:18













2














Try this:



Span<byte> bytes = ...;
string s = Encoding.UTF8.GetString((byte*)Unsafe.AsPointer(ref bytes.GetPinnableReference()),
bytes.Length);





share|improve this answer


























  • Thanks! I did not see GetPinnableReference() anywhere in IntelliSense. However, this did not seem to work for ReadOnlySpan<byte> (it cannot pass it as ref because it is readonly); but it would work for my initial question (only now I realized I have a ReadOnlySpan, sorry!).

    – Ray Koopa
    Jan 18 at 16:00











  • @RayKoopa: the reason you couldn't see the method, by the way, is because it was explicitly hidden as feature. This was back when it was called DangerousGetPinnableReference; it's since been downgraded to "not actually that dangerous", but the method's still hidden.

    – Jeroen Mostert
    Jan 18 at 16:21






  • 1





    The alternative proposed for ReadOnlySpan is not correct! Storing it in a variable first and taking the ref of that gives you a reference to the local byte, not the spanned array. Accessing any element beyond the first this way will give garbage.

    – Jeroen Mostert
    Jan 18 at 16:25











  • @JeroenMostert I actually remember that "Dangerous" method name. I didn't follow up on the recent changes, thanks for clearing this up.

    – Ray Koopa
    Jan 18 at 16:28
















2














Try this:



Span<byte> bytes = ...;
string s = Encoding.UTF8.GetString((byte*)Unsafe.AsPointer(ref bytes.GetPinnableReference()),
bytes.Length);





share|improve this answer


























  • Thanks! I did not see GetPinnableReference() anywhere in IntelliSense. However, this did not seem to work for ReadOnlySpan<byte> (it cannot pass it as ref because it is readonly); but it would work for my initial question (only now I realized I have a ReadOnlySpan, sorry!).

    – Ray Koopa
    Jan 18 at 16:00











  • @RayKoopa: the reason you couldn't see the method, by the way, is because it was explicitly hidden as feature. This was back when it was called DangerousGetPinnableReference; it's since been downgraded to "not actually that dangerous", but the method's still hidden.

    – Jeroen Mostert
    Jan 18 at 16:21






  • 1





    The alternative proposed for ReadOnlySpan is not correct! Storing it in a variable first and taking the ref of that gives you a reference to the local byte, not the spanned array. Accessing any element beyond the first this way will give garbage.

    – Jeroen Mostert
    Jan 18 at 16:25











  • @JeroenMostert I actually remember that "Dangerous" method name. I didn't follow up on the recent changes, thanks for clearing this up.

    – Ray Koopa
    Jan 18 at 16:28














2












2








2







Try this:



Span<byte> bytes = ...;
string s = Encoding.UTF8.GetString((byte*)Unsafe.AsPointer(ref bytes.GetPinnableReference()),
bytes.Length);





share|improve this answer















Try this:



Span<byte> bytes = ...;
string s = Encoding.UTF8.GetString((byte*)Unsafe.AsPointer(ref bytes.GetPinnableReference()),
bytes.Length);






share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 18 at 15:04

























answered Jan 18 at 14:52









mm8mm8

82.9k81831




82.9k81831













  • Thanks! I did not see GetPinnableReference() anywhere in IntelliSense. However, this did not seem to work for ReadOnlySpan<byte> (it cannot pass it as ref because it is readonly); but it would work for my initial question (only now I realized I have a ReadOnlySpan, sorry!).

    – Ray Koopa
    Jan 18 at 16:00











  • @RayKoopa: the reason you couldn't see the method, by the way, is because it was explicitly hidden as feature. This was back when it was called DangerousGetPinnableReference; it's since been downgraded to "not actually that dangerous", but the method's still hidden.

    – Jeroen Mostert
    Jan 18 at 16:21






  • 1





    The alternative proposed for ReadOnlySpan is not correct! Storing it in a variable first and taking the ref of that gives you a reference to the local byte, not the spanned array. Accessing any element beyond the first this way will give garbage.

    – Jeroen Mostert
    Jan 18 at 16:25











  • @JeroenMostert I actually remember that "Dangerous" method name. I didn't follow up on the recent changes, thanks for clearing this up.

    – Ray Koopa
    Jan 18 at 16:28



















  • Thanks! I did not see GetPinnableReference() anywhere in IntelliSense. However, this did not seem to work for ReadOnlySpan<byte> (it cannot pass it as ref because it is readonly); but it would work for my initial question (only now I realized I have a ReadOnlySpan, sorry!).

    – Ray Koopa
    Jan 18 at 16:00











  • @RayKoopa: the reason you couldn't see the method, by the way, is because it was explicitly hidden as feature. This was back when it was called DangerousGetPinnableReference; it's since been downgraded to "not actually that dangerous", but the method's still hidden.

    – Jeroen Mostert
    Jan 18 at 16:21






  • 1





    The alternative proposed for ReadOnlySpan is not correct! Storing it in a variable first and taking the ref of that gives you a reference to the local byte, not the spanned array. Accessing any element beyond the first this way will give garbage.

    – Jeroen Mostert
    Jan 18 at 16:25











  • @JeroenMostert I actually remember that "Dangerous" method name. I didn't follow up on the recent changes, thanks for clearing this up.

    – Ray Koopa
    Jan 18 at 16:28

















Thanks! I did not see GetPinnableReference() anywhere in IntelliSense. However, this did not seem to work for ReadOnlySpan<byte> (it cannot pass it as ref because it is readonly); but it would work for my initial question (only now I realized I have a ReadOnlySpan, sorry!).

– Ray Koopa
Jan 18 at 16:00





Thanks! I did not see GetPinnableReference() anywhere in IntelliSense. However, this did not seem to work for ReadOnlySpan<byte> (it cannot pass it as ref because it is readonly); but it would work for my initial question (only now I realized I have a ReadOnlySpan, sorry!).

– Ray Koopa
Jan 18 at 16:00













@RayKoopa: the reason you couldn't see the method, by the way, is because it was explicitly hidden as feature. This was back when it was called DangerousGetPinnableReference; it's since been downgraded to "not actually that dangerous", but the method's still hidden.

– Jeroen Mostert
Jan 18 at 16:21





@RayKoopa: the reason you couldn't see the method, by the way, is because it was explicitly hidden as feature. This was back when it was called DangerousGetPinnableReference; it's since been downgraded to "not actually that dangerous", but the method's still hidden.

– Jeroen Mostert
Jan 18 at 16:21




1




1





The alternative proposed for ReadOnlySpan is not correct! Storing it in a variable first and taking the ref of that gives you a reference to the local byte, not the spanned array. Accessing any element beyond the first this way will give garbage.

– Jeroen Mostert
Jan 18 at 16:25





The alternative proposed for ReadOnlySpan is not correct! Storing it in a variable first and taking the ref of that gives you a reference to the local byte, not the spanned array. Accessing any element beyond the first this way will give garbage.

– Jeroen Mostert
Jan 18 at 16:25













@JeroenMostert I actually remember that "Dangerous" method name. I didn't follow up on the recent changes, thanks for clearing this up.

– Ray Koopa
Jan 18 at 16:28





@JeroenMostert I actually remember that "Dangerous" method name. I didn't follow up on the recent changes, thanks for clearing this up.

– Ray Koopa
Jan 18 at 16:28


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54255888%2fcan-i-get-a-pointer-to-a-span%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Liquibase includeAll doesn't find base path

How to use setInterval in EJS file?

Petrus Granier-Deferre