创建空的 IAsyncEnumerable
Create empty IAsyncEnumerable
我有一个这样写的界面:
public interface IItemRetriever
{
public IAsyncEnumerable<string> GetItemsAsync();
}
我想写一个 returns 没有项目的空实现,像这样:
public class EmptyItemRetriever : IItemRetriever
{
public IAsyncEnumerable<string> GetItemsAsync()
{
// What do I put here if nothing is to be done?
}
}
如果它是一个普通的 IEnumerable,我会 return Enumerable.Empty<string>();
,但我没有找到任何 AsyncEnumerable.Empty<string>()
。
解决方法
我发现这个有效但很奇怪:
public async IAsyncEnumerable<string> GetItemsAsync()
{
await Task.CompletedTask;
yield break;
}
有什么想法吗?
如果您安装了 System.Linq.Async
软件包,您应该可以使用 AsyncEnumable.Empty<string>()
。这是一个完整的例子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
IAsyncEnumerable<string> empty = AsyncEnumerable.Empty<string>();
var count = await empty.CountAsync();
Console.WriteLine(count); // Prints 0
}
}
如果出于任何原因你不想安装 Jon 的回答中提到的包,你可以像这样创建方法 AsyncEnumerable.Empty<T>()
:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public static class AsyncEnumerable
{
public static IAsyncEnumerator<T> Empty<T>() => EmptyAsyncEnumerator<T>.Instance;
class EmptyAsyncEnumerator<T> : IAsyncEnumerator<T>
{
public static readonly EmptyAsyncEnumerator<T> Instance =
new EmptyAsyncEnumerator<T>();
public T Current => default!;
public ValueTask DisposeAsync() => default;
public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(false);
}
}
注意: 答案并不劝阻使用 System.Linq.Async
包。此答案提供了 AsyncEnumerable.Empty<T>()
的简要实现,适用于您需要它而您 cannot/don 不想使用该包的情况。您可以找到包 here.
中使用的实现
我想避免安装新包,但 实际上并未按照原始问题中的要求实现 IAsyncEnumerable<T>
。这是一个完整的解决方案,它实现了该接口,可以轻松地允许调用 AsyncEnumerable.Empty<T>
的方式与 Enumerable.Empty<T>
今天的工作方式相同。
public static class AsyncEnumerable
{
/// <summary>
/// Creates an <see cref="IAsyncEnumerable{T}"/> which yields no results, similar to <see cref="Enumerable.Empty{TResult}"/>.
/// </summary>
public static IAsyncEnumerable<T> Empty<T>() => EmptyAsyncEnumerator<T>.Instance;
private class EmptyAsyncEnumerator<T> : IAsyncEnumerator<T>, IAsyncEnumerable<T>
{
public static readonly EmptyAsyncEnumerator<T> Instance = new EmptyAsyncEnumerator<T>();
public T Current => default;
public ValueTask DisposeAsync() => default;
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return this;
}
public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(false);
}
}
我有一个这样写的界面:
public interface IItemRetriever
{
public IAsyncEnumerable<string> GetItemsAsync();
}
我想写一个 returns 没有项目的空实现,像这样:
public class EmptyItemRetriever : IItemRetriever
{
public IAsyncEnumerable<string> GetItemsAsync()
{
// What do I put here if nothing is to be done?
}
}
如果它是一个普通的 IEnumerable,我会 return Enumerable.Empty<string>();
,但我没有找到任何 AsyncEnumerable.Empty<string>()
。
解决方法
我发现这个有效但很奇怪:
public async IAsyncEnumerable<string> GetItemsAsync()
{
await Task.CompletedTask;
yield break;
}
有什么想法吗?
如果您安装了 System.Linq.Async
软件包,您应该可以使用 AsyncEnumable.Empty<string>()
。这是一个完整的例子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
IAsyncEnumerable<string> empty = AsyncEnumerable.Empty<string>();
var count = await empty.CountAsync();
Console.WriteLine(count); // Prints 0
}
}
如果出于任何原因你不想安装 Jon 的回答中提到的包,你可以像这样创建方法 AsyncEnumerable.Empty<T>()
:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public static class AsyncEnumerable
{
public static IAsyncEnumerator<T> Empty<T>() => EmptyAsyncEnumerator<T>.Instance;
class EmptyAsyncEnumerator<T> : IAsyncEnumerator<T>
{
public static readonly EmptyAsyncEnumerator<T> Instance =
new EmptyAsyncEnumerator<T>();
public T Current => default!;
public ValueTask DisposeAsync() => default;
public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(false);
}
}
注意: 答案并不劝阻使用 System.Linq.Async
包。此答案提供了 AsyncEnumerable.Empty<T>()
的简要实现,适用于您需要它而您 cannot/don 不想使用该包的情况。您可以找到包 here.
我想避免安装新包,但 IAsyncEnumerable<T>
。这是一个完整的解决方案,它实现了该接口,可以轻松地允许调用 AsyncEnumerable.Empty<T>
的方式与 Enumerable.Empty<T>
今天的工作方式相同。
public static class AsyncEnumerable
{
/// <summary>
/// Creates an <see cref="IAsyncEnumerable{T}"/> which yields no results, similar to <see cref="Enumerable.Empty{TResult}"/>.
/// </summary>
public static IAsyncEnumerable<T> Empty<T>() => EmptyAsyncEnumerator<T>.Instance;
private class EmptyAsyncEnumerator<T> : IAsyncEnumerator<T>, IAsyncEnumerable<T>
{
public static readonly EmptyAsyncEnumerator<T> Instance = new EmptyAsyncEnumerator<T>();
public T Current => default;
public ValueTask DisposeAsync() => default;
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return this;
}
public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(false);
}
}