Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Span<byte> in async method?

Tags:

c#

I am trying to determine valid base64 string in async method using codes below:

public static async Task<bool> IsBase64String(string base64)
{
    Span<byte> buffer = new Span<byte>(new byte[base64.Length]);
    return await Task.FromResult(Convert.TryFromBase64String(base64, buffer, out int bytesParsed));
}

But Span can not be declared in async method, any body please help?

like image 474
Donald Avatar asked Mar 20 '26 22:03

Donald


1 Answers

While Stephen's answer is correct... if you need to use a Span<T> in an async method and you can use C# 7 or above, then you can take advantage of a language feature called local functions to solve for the Parameters or locals of type 'T' cannot be declared in async methods or lambda expressions error. Below is an example of how you could do that... and once again this is meant to solve for the reason given.

using System;
using System.Text;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main(string[] args)
    {
        var base64Str = Convert.ToBase64String(Encoding.UTF8.GetBytes("this is a Base64 str"));
        var notBase64Str = "this is not a Base64 str";
        Console.WriteLine(await IsBase64String(base64Str)); // True
        Console.WriteLine(await IsBase64String(notBase64Str)); // False
    }

    public static async Task<bool> IsBase64String(string base64)
    {
        return await Task.FromResult(CheckIfIsBase64String());
        // Note the use of a local non-async function so you can use `Span<T>`
        bool CheckIfIsBase64String()
        {
            // the use of stackalloc avoids array heap allocation
            Span<byte> buffer = stackalloc byte[base64.Length];
            return Convert.TryFromBase64String(base64, buffer, out int bytesParsed);
        }
    }
}

the code on dotnetfiddle.net

Alternate way using .Net 8 and SearchValues

I've wrapped this in an async method to match the signature from the user's given question. In performant real-world code it would not be needed.

using System;
using System.Text;
using System.Threading.Tasks;

public class Program
{
    private static System.Buffers.SearchValues<char> base64SearchValues = System.Buffers.SearchValues.Create(@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=");
    public async static Task Main(string[] args)
    {
        var base64Str = Convert.ToBase64String(Encoding.UTF8.GetBytes("this is a Base64 str"));
        var notBase64Str = "this is not a Base64 str";
        Console.WriteLine(await IsBase64String(base64Str)); // True
        Console.WriteLine(await IsBase64String(notBase64Str)); // False
        Console.WriteLine(await IsBase64String(null)); // False
        Console.WriteLine(await IsBase64String("")); // False
    }

    public async static Task<bool> IsBase64String(string base64)
    {
        // Note the use of `AsSpan()`
        return await Task.FromResult(
            base64?.Length > 0 &&
            base64?.Length % 4 == 0 &&
            base64.AsSpan().IndexOfAnyExcept(base64SearchValues) < 0
        );
    }
}

the code on dotnetfiddle.net

like image 138
Al Dass Avatar answered Mar 22 '26 13:03

Al Dass



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!