Po tym, jak C # 5 wprowadził model async
i await
programowanie asynchroniczne, społeczność C # doszła do konwencji nazewnictwa, aby dodać sufiks „Async” do metod zwracających oczekiwany typ, taki jak ten:
interface Foo
{
Task BarAsync();
}
Od tego czasu napisano wiele analizatorów kodu statycznego (zarówno opartych na Roslyn, jak i innych), aby polegały na tej konwencji nazewnictwa podczas wykrywania zapachu kodu wokół programowania asynchronicznego.
Teraz, gdy C # 8 wprowadził koncepcję asynchronicznych wyliczeń, które same w sobie nie są oczekiwane, ale mogą być używane w połączeniu z await foreach
, wydaje się, że istnieją dwie opcje zwracania metod nazewnictwa IAsyncEnumerable
:
interface Foo
{
// No "Async" suffix, indicating that the return value is not awaitable.
IAsyncEnumerable<T> Bar<T>();
}
lub
interface Foo
{
// With "Async" suffix, indicating that the overall logic is asynchronous.
IAsyncEnumerable<T> BarAsync<T>();
}
Czy istnieje ostateczna wytyczna dotycząca konwencji nazewnictwa (od zespołu językowego C #, .NET Foundation lub innych organów) dotycząca powyższych opcji, na przykład w jaki sposób konwencja nazewnictwa C # 5 została jednoznacznie ujednolicona i nie została pozostawiona do oceny programistów na podstawie opinii?
async
i użyjawait
wewnątrz), a próbka msdn pokazuje to samoAsync
sufiksu dla metod, które zwracająIAsyncEnumerable
, np . ChannelReader.ReadAllAsync . W innych przypadkach, np. W EF Core,AsAsyncEnumerable()
który jest już jasnyOdpowiedzi:
Nie ma lepszej wytycznej niż to, co już robią zespoły .NET :
IAsyncEnumerable<T>
IAsyncEnumerable
poprzez wywołanie AsAsyncEnumerable ()IAsyncEnumerable
sSystem.Linq.Async
zachowują swoje nazwy. Nie maSelectAsync
lubSelectAsAsyncEnumerable
po prostuSelect
.We wszystkich przypadkach jasne jest, jaki jest wynik metody. We wszystkich przypadkach
await foreach
przed użyciem można oczekiwać wyników tej metody .Tak więc prawdziwa wytyczna pozostaje taka sama - upewnij się, że nazwa wyjaśnia zachowanie :
AsAsyncEnumerable()
lubToAsyncEnumerable()
, nie trzeba dodawać żadnego przyrostka.Async
przyrostek, aby programiści wiedzieli, że potrzebująawait foreach
wyniku.Analizatory kodu i generatory tak naprawdę nie dbają o nazwy metod, wykrywają zapachy, sprawdzając sam kod. Analizator kod powie Ci, że zapomniał czekają zadania lub nieważne jak nazwać metody i zmienne. Generator może po prostu użyć odbicia do sprawdzenia i emisji
await foreach
IAsyncEnumerable
IAsyncEnumerable
await foreach
To styl analizatorów, które sprawdzają nazwiska. Ich zadaniem jest zapewnienie spójnego stylu kodu, aby programiści mogli go zrozumieć. Analizator stylów powie ci, że metoda nie jest zgodna z wybranym stylem. Ten styl może być przewodnikiem zespołu lub powszechnie akceptowanym stylem.
I oczywiście wszyscy wiedzą, że wspólny przedrostek dla pól prywatnych wystąpień to
_
:)źródło
ChannelReader.ReadAllAsync
przykładu. Ponieważ pochodzi to prosto od zespołu .NET, ciężko jest pójść nie tak.To nie jest metoda asynchroniczna, więc nazwa nie powinna kończyć się na „Async”. Ten przyrostek metody jest konwencją mającą na celu wyjaśnienie, że należy oczekiwać metody lub że wynik powinien być traktowany jako zadanie.
Myślę, że normalna nazwa zwracająca kolekcję jest odpowiednia. GetFoos () lub podobny.
źródło
Async
sufiksu. Sufiks jest używany w samym .NET Core: ChannelReader.ReadAllAsync zwraca IAsyncEnumerable.IAsyncEnumerable
Musi być stosowany zawait foreach
, więc przyrostek sens.Sufiks asynchroniczny, a nawet słowo kluczowe,
async
jest po prostu bojlerem, nie ma znaczenia poza niektórymi argumentami wstecznej kompatybilności. C # ma wszystkie informacje do odróżnienia tych funkcji, tak jak odróżnia sięyield
w metodach, które zwracająIEnumerable
, ponieważ wiesz, że nie musisz dodawać niczego takiegoenumerable
ani żadnego innego słowa kluczowego do takich metod.Musisz dodać sufiks Async tylko dlatego, że C # będzie narzekać na przeciążenia, więc zasadniczo te dwa są identyczne i robią to samo według wszystkich reguł polimorfizmu (jeśli nie bierzemy pod uwagę czynnika umyślnego korupcji):
Ale nie można tego tak napisać, ponieważ kompilator będzie narzekał. Ale hej! Połknie tę potworność:
a nawet to:
Więc to jest to. Dodasz ASYNC tylko do zatrzymania kompilatora narzekać. Nie wyjaśniać rzeczy. Nie po to, żeby były lepsze. Jeśli nie ma na co narzekać - nie ma powodu, aby go dodawać, więc w twoim przypadku uniknę tego, chyba że stanie się
Task<IAsyncEnumerable>
.PS: Dla lepszego zrozumienia całego obrazu tutaj - jeśli kiedyś w przyszłości ktoś doda rozszerzenia metody kwantowo-komputerowej C # (fantazy, huh), które będą działały w innym paradygmacie, prawdopodobnie będziemy potrzebować innego sufiksu jak Quant lub coś takiego, ponieważ C # będzie narzekać inaczej. Będzie to dokładnie ta sama metoda, ale zadziała to w inny sposób. Podobnie jak polimorfizm. Podobnie jak interfejsy.
źródło