Что возвращать, Empty collection или null?

Собственно сам вопрос, что считается лучшей практикой, вернуть Enumerable.Empty() или null? И указывать возвращаемым типом List или IEnumerable?
Например есть метод возвращающий список адресов, какой вариант будет правильным?
public IEnumerable<Adresses> GetAdresses()
        {
            try
            {
                 return dbContext.Adresses.ToList();
            }
            catch (Exception)
            {
                return Enumerable.Empty<Adresses>();
            }
        }

или
public List<Adresses> GetAdresses()
        {
            try
            {
                 return dbContext.Adresses.ToList();
            }
            catch (Exception)
            {
                return null;//или что-нибудь вроде new List<Adresses>
            }
        }

И хотелось бы объяснений.
  • Вопрос задан
  • 1681 просмотр
Решения вопроса 1
@dmitryKovalskiy
программист средней руки
Лучше вернуть пустой список. Бизнес-логика как правило проверяет коллекцию на наличие хоть каких-то элементов(Count/Length>0) или по признаку (Where().Count/Length>0). Возврат NULL предварит эти проверки доп. проверкой на NULL. Лично вы из каких соображений хотите вернуть NULL?
UPD: Есть альтернатива - постоянно ловить NullReferenceException, но с тем же успехом можете использовать оператор goto.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
orlov0562
@orlov0562
I'm cool!
Конечно пустую коллекцию.. у тебя даже об этом сигнатура говорит. В случае с Null ты не сможешь передать результат дальше (в функцию принимающую List<Adresses>) без дополнительных проверок. А вообще, очень многое зависит от требования и контекста, в последнем случае, например, можно кидать соответствующий exception (говорящий о пустом списке), который дальше уже будет обрабатываться. Но, мне кажется логичней вернуть пустую коллекцию заданного типа.
Ответ написан
Комментировать
@i_light
Backend, XAML, crossplatform
Лучше вернуть OperationResult в обоих случаях, например такой:

public class OperationResult<T>
{
     T Result { get; set; }
     string Message { get; set; }
     bool IsSuccessful { get; set; } // можно заменить на enum с бОльшим количеством вариантов
}
Ответ написан
Комментировать
Valeriy1991
@Valeriy1991
Разработчик .NET C# (ASP.NET MVC) в Alfa-B, Moscow
Добрый день!

Правильным будет следующий вариант:

public IEnumerable<Adresses> GetAdresses()
        {
            try
            {
                 return dbContext.Adresses.ToList();
            }
            catch (Exception ex)
            {
                // Логируем ошибку - что-то вроде:
                //_loggerService.Error(ex);
                throw;
            }
        }


А снаружи, например, у Вас будет метод, который при ловле исключения будет выдавать что-то осознанное пользователю:
public ActionResult Addresses()
        {
            try
            {
                 var addressList = _dataService.GetAdresses();
                 return View("_Addresses", addressList);
            }
            catch (Exception ex)
            {
                TempData["Error"] = "Не удалось загрузить список адресов. Попробуйте позже."
                 return View("_Addresses");
            }
        }


Во View я бы тоже советовал всегда делать проверку на null, потому что по независящим от Вас причинам Model спокойно может быть null. И лучше на клиенте такие ситуации обрабатывать, чтобы у Ваших пользователей не было ступора и они не перестали пользоваться Вашим веб-приложением.
<div>
@if(Model != null && Model.Any())
{
   <div>
       @foreach(var address in Model)
       {
           @*Здесь вывод Ваших адресов*@
       }
   </div>
}
else
{
    <div>
        @TempData["Error"]
    </div>
}
</div>
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы