我有一个这样编写的接口:
public interface IItemRetriever
{
public IAsyncEnumerable<string> GetItemsAsync();
}
我想编写一个不返回任何项目的空实现,如下所示:
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;
}
有什么主意吗?
答案 0 :(得分:21)
如果安装System.Linq.Async
软件包,则应该可以使用# Working Example of how to pass parameters to sequential windows
import tkinter as tk
class Win1(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.grid()
rownum = 0
colnum = 0
#-----collect some information needed for the application--------------------------
self.lbl_a = tk.Label(self, text="Number of Categories", font=("Arial Bold", 10),
justify="left",anchor='w')
self.lbl_a.grid(column=colnum, row=rownum,columnspan=1,sticky='w')
self.numcat_ent =tk.Entry(self, width=12,background='white',
fg='blue',state='normal',font=("Arial Bold", 10), justify='center')
self.numcat_ent.insert('end', '4')
self.numcat_ent.grid(column=colnum+1, row=rownum)
numcat=int(self.numcat_ent.get())
rownum += 1
self.lbl_b = tk.Label(self, text="Items Per Category", font=("Arial Bold", 10),
justify="left",anchor='w')
self.lbl_b.grid(column=colnum, row=rownum,columnspan=1,sticky='w')
items=6
self.numitems_ent=tk.Entry(self, width=12,background='white',
fg='blue',state='normal',font=("Arial Bold", 10), justify='center')
self.numitems_ent.insert('end', '4')
self.numitems_ent.grid(column=colnum+1, row=rownum)
numitems=int(self.numitems_ent.get())
rownum += 1
#---on click, open Win2 and close Win1
btn1=tk.Button(self,text='Show Win 2',
command=lambda: self.open_win2(master,numcat ,numitems))
btn1.grid(row=rownum,column=colnum,sticky='nsew')
def open_win2(self, master, numcat ,numitems):
self.hide(master)
self.root2 = tk.Toplevel()
self.root2.geometry('300x600')
print(numcat,numitems)
app2 = Win2(self.root2,root, numcat, numitems)
def hide(self,master):
root.withdraw()
#---to bring root window back
#root.deiconify()
class Win2(tk.Frame):
def __init__(self, master, root2, parm1, parm2):
tk.Frame.__init__(self, master)
print(parm1, parm2)
root.withdraw()
self.grid()
#---on click, open Win3 form and close Win2
self.btn1=tk.Button(self,text='Open Win3', command=lambda: self.open_win3(master))
self.btn1.grid(row=0,column=0)
rownum = 0
colnum = 0
fontSize = 12
for i in range(parm1):
rownum += 1
self.catEntry=tk.Entry(self, width=12,background='white',
fg='blue',state='normal',font=("Arial Bold", fontSize), justify='center')
self.catEntry.grid(column=colnum, row=rownum)
for j in range(parm2):
rownum += 1
self.subcatEntry=tk.Entry(self, width=12,background='white',
fg='black',state='normal',font=("Arial Bold", fontSize), justify='center')
self.subcatEntry.grid(column=colnum+1, row=rownum)
def open_win3(self,master):
self.hide(master)
root3 = tk.Toplevel()
root3.geometry('800x800')
app3 = Win3(root3)
def hide(self,master):
root.withdraw()
master.withdraw()
class Win3(tk.Frame):
def __init__(self,master):
root.withdraw()
tk.Frame.__init__(self, master)
self.grid()
self.btn=tk.Button(self,text='Return to Start Page',command=lambda:self.return_to_start(master))
self.btn.grid(row=0,column=0)
def return_to_start(self, master):
master.withdraw()
root.deiconify()
root = tk.Tk()
root.geometry("225x100")
app = Win1(root)
#----Mainloop keeps forms updated and listens for user input--
root.mainloop()
。这是一个完整的示例:
AsyncEnumable.Empty<string>()
答案 1 :(得分:6)
如果由于某种原因您不想安装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>()
的简要实现。您可以在软件包here中找到使用的实现。
答案 2 :(得分:-1)
我想避免安装新软件包,但 previous answer 实际上并未按照原始问题的要求实现 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);
}
}