Determining the region from several sources of information The task is to determine the region by comparing three sources of information taking into account the coefficients of their importance.

//GetRegionIdByKeywordAsync returns region id by string name, if the region could not be determined, 0 will return

//The received identifiers can completely or partially coincide, or be absolutely different
int regionIdByIp = await GetRegionIdByKeywordAsync(regionByIpStr);
int regionIdByPhone = await GetRegionIdByKeywordAsync(regionByPhoneStr);
int regionIdByInput = await GetRegionIdByKeywordAsync(regionByInputStr);

var weights = new List&lt;KeyValuePair&lt;int, int&gt;&gt;
{
  //Each source of information has its own importance coefficient, determined manually
  new KeyValuePair&lt;int, int&gt;(regionIdByIp, 5),
  new KeyValuePair&lt;int, int&gt;(regionIdByPhone, 3),
  new KeyValuePair&lt;int, int&gt;(regionIdByInput, 4)
};

//The final decision is determined by the search for a region that has the highest score in the total
int regionId = weights.Where(x =&gt; x.Key != default(int)).GroupBy(kvp =&gt; kvp.Key).OrderByDescending(x =&gt; x.Sum(y =&gt; y.Value)).Select(x =&gt; x.Key).FirstOrDefault();


Do you see any improvement / issue?
Since you are not actually using a dictionary I find anonymous tuples would be much more readable here. Consider this where you don't even need a List&lt;T&gt; but just a simple array:

var weights = new (int RegionId, int Importance)[]
{
  (regionIdByIp, 5),
  (regionIdByPhone, 3),
  (regionIdByInput, 4)
};


Where you define such a tuple as (int RegionId, int Importance). With it the next query (also written with line breaks) would be much easier to understand.

int mostImportantRegionId = 
    weights
        .Where(x =&gt; x.RegionId &gt; 0)
        .GroupBy(kvp =&gt; kvp.RegionId)
        .OrderByDescending(x =&gt; x.Sum(y =&gt; y.Importance))
        .Select(x =&gt; x.RegionId)
        .FirstOrDefault();


I also think that x.Key != default(int) is a strage condition. If Key is an id then it probably should be greater than 0 so it's better to write x.RegionId &gt; 0 instead.



What you also can do better is the await part. Currently you wait for each task to finish one-by-one. Let's them work in parallel with WaitAll:

var regionIdByIpTask = GetRegionIdByKeywordAsync(regionByIpStr);
var regionIdByPhoneTask = GetRegionIdByKeywordAsync(regionByPhoneStr);
var regionIdByInputTask = GetRegionIdByKeywordAsync(regionByInputStr);

Task.WaitAll(new [] 
{
    regionIdByIpTask,
    regionIdByPhoneTask,
    regionIdByInputTask
};


Now you can build your weights:

var weights = new (int RegionId, int Importance)[]
{
  (regionIdByIpTask.Result, 5),
  (regionIdByPhoneTask.Result, 3),
  (regionIdByInputTask.Result, 4)
};