awaitable 한 nullable delegate 를 await 키워드와 ? 를 동시에 쓸 수 있는 방법이 있을까요?

awaitable 하지 않은 델리게이트이거나 await 하지 않고 호출하는 델리게이트의 경우
델리게이트가 null 인지 여부를 ? 키워드를 통해 사용할 수 있지요.

Func<string> func = null;
func?.Invoke();

뭐 요딴식으루 말이죠.

근데 awaitable 한 델리게이트를 await 과 함께 사용하면
? 키워드로 null 체크 식을 사용할 수가 없어욜…

Func<Task> func = null;	
await func?.Invoke();

이건 사실 문법적으로도 말이 안 되긴 해요.
(func 가 null 이면 await 키워드가 에러죠.)

그래서 그냥 null 체크 조건문을 만들어 쓰긴 합니다.

Func<Task> func = null;	

if (func is not null)
{
	await func();	
}

아…
근데 저 ? 키워드를 사용해서 식으루 표현하는 게 참 아숩단 말이죵… ;ㅂ;

혹시 방법이 있을까요?ㅅ?

아님 혹시 다른 분들은 어떻게 사용하시나욜?ㅂ?

3개의 좋아요

세가지 정도 방법이 있지 않을까 합니다. 저 같은 경우 첫번째 방법을 선호합니다.

첫번째 방법 : null은 없다

Func<Task> funcAsync = () => Task.CompletedTask;
await funcAsync();

funcAsyncnull을 허용하지 않습니다. 그러므로 편하게 await을 사용할 수 있습니다.
단점은 프로젝트 설정에 <Nullable>enable</Nullable>을 줄 수 있는 환경만 해당되겠습니다.

두번째 방법 : null인 경우 Task.CompletedTask 호출

Func<Task>? funcAsync2 = null;
await (funcAsync2?.Invoke() ?? Task.CompletedTask);

??를 이용해 null인 경우 Task.CompleteTask를 반환하도록 합니다. 어쨌든 한줄로 쓸 수 있어서 조금 보완된 느낌입니다만 깔끔해 보이지는 않습니다.

세번째 방법 : 확장 메소드로 좀 더 깔끔하게

Func<Task>? funcAsync3 = null;
await funcAsync3.InvokeAsync();

public static class FuncTaskExtension
{
    public static Task InvokeAsync(this Func<Task>? @this) => @this?.Invoke() ?? Task.CompletedTask;
}

이건 사실 두번째 방법을 좀 더 깔끔하게 사용하는 방법입니다.

4개의 좋아요
func?.Invoke().ContinueWith(...);

이 방법도 있습니다.

3개의 좋아요

원츄!

1개의 좋아요

음… 이렇게 하면 async / await 를 사용 못 할 거 같은디요… ㅇㅁㅇ?

1개의 좋아요

아… async/await 키워드 관점에서는 사용할 수 없겠네요…
다만 동작으로 바라본다면 꽤 요긴하게 쓰이긴 합니다 :slightly_smiling_face:

1개의 좋아요