6
\$\begingroup\$

Consider we have three different database stores which we want to find an Id which is unique in all this three. I mean if we query first data store and we find that id. It's over and there is no need to further attempt, if that Id is in non of this three data stores we return null, I'm new in asynchronous programming, I wanted to know if there is any better implementation for this lines of code? I mean less if/else?

 public async Task<WebData> GetDataByIdAsync(GetDataById input)
    {
        var twitterData = await DataAccess.FindDataById<TwitterData>(input.Id);
        WebData result;
        if (twitterData  == null)
        {
            var facebookData = await DataAccess.FindDataById<FacebookData>(input.Id);
            if facebookData == null)
            {
                var linkedinData = await DataAccess.FindDataById<LinkedinData>(input.Id);
                if linkedinData == null)
                {
                    return null;
                }
                result = linkedinData 
            }
            else
            {
                result = facebookData;
            }
        }
        else
        {
            result = twitterData ;
        }
        return result;
    }
\$\endgroup\$
0

3 Answers 3

21
\$\begingroup\$

Use the return pattern:

public async Task<WebData> GetDataByIdAsync(GetDataById input) 
{ 
    var twitterData = await DataAccess.FindDataById<TwitterData>(input.Id); 
    if (twitterData != null)
    {
        return twitterData;
    } 

    var facebookData = await DataAccess.FindDataById<FacebookData>(input.Id); 
    if (facebookData != null) 
    {
        return facebookData;
    } 

    var linkedinData = await DataAccess.FindDataById<LinkedinData>(input.Id); 
    if (linkedinData != null) 
    { 
        return linkedinData; 
    }

    return null;
}
\$\endgroup\$
8
  • 7
    \$\begingroup\$ Are early returns a "pattern" now? \$\endgroup\$
    – Bergi
    Jan 4, 2018 at 19:40
  • 1
    \$\begingroup\$ What is actually needed to be called a pattern? \$\endgroup\$ Jan 4, 2018 at 19:52
  • 1
    \$\begingroup\$ @ABravoDev: Multiple steps/parts that commonly appear together to solve a common problem, but are not baked into the language. \$\endgroup\$
    – cHao
    Jan 4, 2018 at 21:56
  • 1
    \$\begingroup\$ This is crying out for a method to call some DAO with an id. You can the same code 3 times. \$\endgroup\$ Jan 5, 2018 at 9:43
  • 2
    \$\begingroup\$ @Bergi Probably a code style pattern, not software design pattern. \$\endgroup\$
    – interphx
    Jan 5, 2018 at 11:04
52
\$\begingroup\$

Short and clean using null-coalescing operator:

public async Task<WebData> GetDataByIdAsync(GetDataById input) 
{ 
    return await DataAccess.FindDataById<TwitterData>(input.Id)?? 
           await DataAccess.FindDataById<FacebookData>(input.Id)??
           await DataAccess.FindDataById<LinkedinData>(input.Id); 
}
\$\endgroup\$
2
2
\$\begingroup\$

An efficient way of doing this (if you don't care about the overhead on the data stores) would be to start all three tasks, then return when the first of the tasks produces a non-null value. Something like this:

public async Task<WebData> GetDataByIdAsync(GetDataById input) 
{
    var remainingTasks = new HashSet<Task<WebData>>(new [] { DataAccess.FindDataById<TwitterData>(input.Id), DataAccess.FindDataById<FacebookData>(input.Id), DataAccess.FindDataById<LinkedinData>(input.Id) });

    while (remainingTasks.Any())
    {
        var firstCompleted = await Task.WhenAny(remainingTasks);
        if (firstCompleted.Result != null)
        {
             return firstCompleted.Result;
        }
        remainingTasks.Remove(firstCompleted);
    }

    return null;
}
\$\endgroup\$
2
  • \$\begingroup\$ One downside to this approach is that you launch all three tasks and if one returns, any exceptions thrown by the later tasks go unobserved. \$\endgroup\$
    – Dan Bryant
    Jan 4, 2018 at 16:07
  • 1
    \$\begingroup\$ This wouldn't work if you cared about order, would it? e.g. if Facebook is fastest but you would prefer to use Twitter if available? Also, it's effectively non-deterministic and could produce different results if you run it multiple times. \$\endgroup\$
    – Bob
    Jan 5, 2018 at 1:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.