Должны ли функции возвращать значение null или пустой объект?

StackOverflow https://stackoverflow.com/questions/1626597

Вопрос

Что лучшая практика при возврате данных из функций.Что лучше вернуть Null или пустой объект?И почему нужно делать одно лучше другого?

Учти это:

public UserEntity GetUserById(Guid userId)
{
     //Imagine some code here to access database.....

     //Check if data was returned and return a null if none found
     if (!DataExists)
        return null; 
        //Should I be doing this here instead? 
        //return new UserEntity();  
     else
        return existingUserEntity;
}

Давайте представим, что в этой программе могут быть действительные случаи, когда в базе данных не будет информации о пользователе с этим GUID.Я полагаю, что в этом случае было бы нецелесообразно создавать исключение??Также у меня сложилось впечатление, что обработка исключений может снизить производительность.

Это было полезно?

Решение

Возврат нулевого значения обычно является лучшей идеей, если вы намереваетесь указать, что данные недоступны.

Пустой объект подразумевает, что данные были возвращены, тогда как возвращение нуля ясно указывает на то, что ничего не было возвращено.

Кроме того, возвращение нулевого значения приведет к нулевому исключению, если вы попытаетесь получить доступ к элементам в объекте, что может быть полезно для выделения ошибочного кода - попытка получить доступ к элементу ничего не имеет смысла. Доступ к членам пустого объекта не завершится неудачей, а это значит, что ошибки могут остаться незамеченными.

Другие советы

Это зависит от того, что наиболее целесообразно для вашего случая.

Имеет ли смысл возвращать ноль, например, " такой пользователь не существует "?

Или имеет смысл создать пользователя по умолчанию? Это имеет смысл, если вы можете с уверенностью предположить, что если пользователь НЕ существует, вызывающий код намеревается существовать, когда его об этом попросят.

Или имеет смысл генерировать исключение (в виде «FileNotFound»), если вызывающий код требует пользователя с недопустимым идентификатором?

Однако - с точки зрения разделения интересов / SRP, первые два являются более правильными. И технически первый является наиболее правильным (но только на волосок) - GetUserById должен отвечать только за одну вещь - получение пользователя. Обработка собственного "пользователь не существует" возвращение чего-либо еще может быть нарушением ПСП. Разделение на другую проверку - bool DoesUserExist (id) будет уместно, если вы решите выбросить исключение.

На основании подробных комментариев ниже : если это вопрос разработки на уровне API, этот метод может быть аналогом " OpenFile " или " ReadEntireFile " ;. Мы "открываем" пользователь из какого-либо хранилища и гидратирование объекта из результирующих данных. Исключение может быть уместным в этом случае. Это может быть не так, но это может быть.

Все подходы приемлемы - это зависит только от более широкого контекста API / приложения.

Лично я использую NULL. Это дает понять, что нет данных для возврата. Но есть случаи, когда нулевой объект может оказаться полезным.

Если вы возвращаете тип массива, тогда возвращайте пустой массив, в противном случае возвращайте ноль.

Вы должны выбросить исключение (только), если конкретный договор нарушен.
В вашем конкретном примере, запрашивая UserEntity на основе известного идентификатора, это будет зависеть от того, является ли пропущенный (удаленный) пользователь ожидаемым случаем. Если это так, верните null , но если это не ожидаемый случай, генерируйте исключение.
Обратите внимание, что если бы функция называлась UserEntity GetUserByName (имя строки) , она, вероятно, не выдает, а возвращает ноль. В обоих случаях возврат пустого UserEntity будет бесполезным.

Для строк, массивов и коллекций ситуация обычно отличается. Я помню некоторую директиву MS, согласно которой методы должны принимать null как «пустой» список, но возвращать коллекции нулевой длины, а не null . То же самое для строк. Обратите внимание, что вы можете объявить пустые массивы: int [] arr = new int [0];

Это бизнес-вопрос, зависящий от того, является ли существование пользователя с определенным идентификатором Guid ожидаемым нормальным сценарием использования этой функции, или же это аномалия, которая не позволяет приложению успешно завершить выполнение любой функции этого метода предоставление объекта пользователя ...

Если это «исключение», то есть отсутствие пользователя с таким идентификатором не позволит приложению успешно завершить выполнение любой выполняемой им функции (например, мы создаем счет-фактуру для клиента, которого мы отправили в продукт). to ...), тогда эта ситуация должна вызвать исключение ArgumentException (или другое пользовательское исключение).

Если с пропавшим пользователем все в порядке (один из возможных нормальных результатов вызова этой функции), тогда верните нулевое значение ....

РЕДАКТИРОВАТЬ: (чтобы ответить на комментарий Адама в другом ответе)

Если приложение содержит несколько бизнес-процессов, один или несколько из которых требуют, чтобы пользователь успешно завершил свою работу, и один или несколько из них могут успешно завершиться без участия пользователя, то исключение следует выдвинуть дальше вверх по стеку вызовов, ближе к тому месту, где бизнес-процессы, которые требуют от пользователя, вызывают этот поток выполнения. Методы между этим методом и той точкой (где генерируется исключение) должны просто сообщать, что пользователь не существует (null, boolean, что угодно - это деталь реализации).

Но если бы все процессы в приложении требовали пользователя, я бы все равно бросил исключение в этом методе ...

Лично я бы возвратил ноль, потому что именно так я и ожидал бы действовать слой DAL / Repository.

Если его не существует, не возвращайте ничего, что могло бы быть истолковано как успешное извлечение объекта, null прекрасно работает здесь.

Самое важное - быть непротиворечивым на уровне DAL / Repos, чтобы не запутаться в его использовании.

Я склонен

  • return null если идентификатор объекта не существует, если заранее неизвестно, существует ли он должен существовать.
  • throw если идентификатор объекта не существует, когда он должен существовать.

Я различаю эти два сценария с помощью этих трех типов методов.Первый:

Boolean TryGetSomeObjectById(Int32 id, out SomeObject o)
{
    if (InternalIdExists(id))
    {
        o = InternalGetSomeObject(id);

        return true;
    }
    else
    {
        return false;
    }
}

Второй:

SomeObject FindSomeObjectById(Int32 id)
{
    SomeObject o;

    return TryGetObjectById(id, out o) ? o : null;
}

Третий:

SomeObject GetSomeObjectById(Int32 id)
{
    SomeObject o;

    if (!TryGetObjectById(id, out o))
    {
        throw new SomeAppropriateException();
    }

    return o;
}

Еще один подход заключается в передаче объекта обратного вызова или делегата, который будет работать со значением. Если значение не найдено, обратный вызов не вызывается.

public void GetUserById(Guid id, UserCallback callback)
{
    // Lookup user
    if (userFound)
        callback(userEntity);  // or callback.Call(userEntity);
}

Это хорошо работает, когда вы хотите избежать нулевых проверок во всем коде, и если не найти значение, это не ошибка. Вы также можете предоставить обратный вызов, если объекты не найдены, если вам нужна какая-либо специальная обработка.

public void GetUserById(Guid id, UserCallback callback, NotFoundCallback notFound)
{
    // Lookup user
    if (userFound)
        callback(userEntity);  // or callback.Call(userEntity);
    else
        notFound(); // or notFound.Call();
}

Тот же подход с использованием одного объекта может выглядеть следующим образом:

public void GetUserById(Guid id, UserCallback callback)
{
    // Lookup user
    if (userFound)
        callback.Found(userEntity);
    else
        callback.NotFound();
}

С точки зрения дизайна мне действительно нравится этот подход, но он имеет недостаток, заключающийся в том, что сайт вызова становится более объемным в языках, которые не поддерживают функции первого класса.

Мы используем CSLA.NET и придерживаемся мнения, что неудачная выборка данных должна возвращать " пустую " объект. Это на самом деле довольно раздражает, так как требует соглашения о том, проверять, является ли obj.IsNew вместо obj == null .

Как упоминалось в предыдущем постере, возвращаемые значения NULL приведут к немедленному сбою кода, что уменьшит вероятность скрытых проблем, вызванных пустыми объектами.

Лично я думаю, что null более элегантно.

Это очень распространенный случай, и я удивлен, что люди здесь удивляются этому: в любом веб-приложении данные часто выбираются с помощью параметра querystring, который, очевидно, может быть искажен, поэтому требуется, чтобы разработчик обрабатывал случаи " не найден ".

Вы можете справиться с этим следующим образом:

if (User.Exists(id)) {
  this.User = User.Fetch(id);
} else {
  Response.Redirect("~/notfound.aspx");
}

... но это дополнительный вызов в базу данных каждый раз, что может быть проблемой на страницах с большим трафиком. Принимая во внимание:

this.User = User.Fetch(id);

if (this.User == null) {
  Response.Redirect("~/notfound.aspx");
}

... требуется только один звонок.

Я предпочитаю null , поскольку он совместим с оператором объединения нулей ( ?? ).

Я бы сказал, верните ноль вместо пустого объекта.

Но конкретный экземпляр, который вы упомянули здесь, вы ищете пользователя по идентификатору пользователя, который является своего рода ключом к этому пользователю, в этом случае я бы, вероятно, захотел бросить исключение, если нет экземпляра пользователя. Полем

Это правило, которому я обычно следую:

  • Если результат не найден на поиске первичной операции ключа, добавьте ObjectNotFoundException.
  • Если результат не найден на поиске каких -либо других критериев, верните NULL.
  • Если результат не найден на поиске неки-критериями, которые могут вернуть несколько объектов, вернуть пустую коллекцию.

Это будет зависеть от контекста, но я обычно возвращаю ноль, если я ищу один конкретный объект (как в вашем примере), и возвращаю пустую коллекцию, если я ищу набор объектов, но их нет .

Если вы допустили ошибку в своем коде и возвращение нулевого значения приводит к исключениям нулевого указателя, то чем раньше вы поймете это, тем лучше. Если вы возвращаете пустой объект, его первоначальное использование может работать, но вы можете получить ошибки позже.

Лучше всего в этом случае вернуть «null», если такого пользователя нет.Также сделайте свой метод статическим.

Редактировать:

Обычно подобные методы являются членами некоторого класса «Пользователь» и не имеют доступа к членам его экземпляра.В этом случае метод должен быть статическим, в противном случае вам необходимо создать экземпляр «Пользователя», а затем вызвать метод GetUserById, который вернет другой экземпляр «Пользователя».Согласитесь, это сбивает с толку.Но если метод GetUserById является членом какого-либо класса «DatabaseFactory» — без проблем оставить его как член экземпляра.

Я лично возвращаю экземпляр объекта по умолчанию. Причина в том, что я ожидаю, что метод вернет ноль ко многим или ноль к единице (в зависимости от цели метода). Единственная причина, по которой при таком подходе это будет состояние ошибки любого рода, заключается в том, что метод не возвратил ни одного объекта (объектов), и от него всегда ожидали (в единицах или в единственном числе).

Что касается предположения, что это вопрос бизнес-сферы - я просто не вижу его с той стороны уравнения. Нормализация типов возвращаемых данных является допустимым вопросом архитектуры приложения. По крайней мере, он подлежит стандартизации в практике кодирования. Я сомневаюсь, что есть бизнес-пользователь, который собирается сказать «в сценарии X, просто дать ему нулевое значение».

В наших бизнес-объектах у нас есть 2 основных метода Get:

Для простоты в контексте, или вы задаете вопрос, они будут:

// Returns null if user does not exist
public UserEntity GetUserById(Guid userId)
{
}

// Returns a New User if user does not exist
public UserEntity GetNewOrExistingUserById(Guid userId)
{
}

Первый метод используется при получении конкретных сущностей, второй метод используется специально при добавлении или редактировании сущностей на веб-страницах.

Это позволяет нам иметь лучшее из обоих миров в контексте, где они используются.

Я французский студент по ИТ, так что извините за мой плохой английский. В наших классах нам говорят, что такой метод никогда не должен возвращать ни null, ни пустой объект. Пользователь этого метода должен сначала проверить, что объект, который он ищет, существует, прежде чем пытаться его получить.

Используя Java, нас просят добавить assert существующие (объект): " Вы не должны пытаться получить доступ к объекту, который не существует " ;; в начале любого метода, который мог возвратить нуль, чтобы выразить «предусловие» (Я не знаю, что это за слово на английском).

IMO, это действительно не просто в использовании, но это то, что я использую, ожидая чего-то лучшего.

Если случай, когда пользователь не найден, встречается достаточно часто, и вы хотите иметь дело с этим различными способами, в зависимости от обстоятельств (иногда выбрасывая исключение, иногда подставляя пустого пользователя), вы также можете использовать что-то близкое к F #. Option или тип Maybe в Haskell, который явно отделяет регистр «без значения» от «нашел что-то!». Код доступа к базе данных может выглядеть следующим образом:

public Option<UserEntity> GetUserById(Guid userId)
{
 //Imagine some code here to access database.....

 //Check if data was returned and return a null if none found
 if (!DataExists)
    return Option<UserEntity>.Nothing; 
 else
    return Option.Just(existingUserEntity);
}

И использовать так:

Option<UserEntity> result = GetUserById(...);
if (result.IsNothing()) {
    // deal with it
} else {
    UserEntity value = result.GetValue();
}

К сожалению, кажется, что каждый бросает подобный себе тип.

Я обычно возвращаю ноль. Он обеспечивает быстрый и простой механизм, позволяющий обнаружить, что что-то напортачило, без исключений и использования множества проб и ошибок повсюду.

Для типов коллекций я бы возвращал пустую коллекцию, для всех остальных типов я предпочитаю использовать шаблоны NullObject для возврата объекта, реализующего тот же интерфейс, что и возвращаемый тип.подробности о выкройке смотрите текст ссылки

Используя шаблон NullObject, это будет: -

public UserEntity GetUserById(Guid userId)

{// Представьте себе какой -то код, чтобы получить доступ к базе данных .....

 //Check if data was returned and return a null if none found
 if (!DataExists)
    return new NullUserEntity(); //Should I be doing this here instead? return new UserEntity();  
 else
    return existingUserEntity;

}

class NullUserEntity: IUserEntity { public string getFirstName(){ return ""; } ...} 

Чтобы выразить то, что говорили другие, более содержательно ...

Исключения для исключительных обстоятельств

Если этот метод является чистым уровнем доступа к данным, я бы сказал, что с учетом некоторого параметра, который включается в оператор выбора, можно ожидать, что я не смогу найти никаких строк, из которых можно построить объект, и, следовательно, возвращение нуля будет приемлемо, так как это логика доступа к данным.

С другой стороны, если бы я ожидал, что мой параметр будет отражать первичный ключ, и мне нужно вернуть только одну строку, если я получу больше одного, я бы сгенерировал исключение. 0 - нормально, чтобы вернуть ноль, 2 - нет.

Теперь, если у меня есть какой-нибудь код входа в систему, который проверен у провайдера LDAP, а затем проверен у БД, чтобы получить более подробную информацию, и я ожидал, что они должны быть синхронизированы всегда, тогда я мог бы выбросить исключение. Как говорили другие, это бизнес-правила.

Теперь я скажу, что это общее правило. Есть моменты, когда вы можете сломать это. Тем не менее, мой опыт и эксперименты с C # (много чего) и Java (кое-что из этого) научили меня, что намного обходиться с производительностью при работе с исключениями гораздо дороже, чем обрабатывать предсказуемые проблемы с помощью условных выражений. логика. Я говорю с мелодией на 2 или 3 порядка дороже в некоторых случаях. Поэтому, если возможно, что ваш код окажется в цикле, я бы посоветовал вернуть значение null и проверить его.

Простите мой псевдо-php/код.

Я думаю, что это действительно зависит от предполагаемого использования результата.

Если вы собираетесь отредактировать/изменить возвращаемое значение и сохранить его, верните пустой объект.Таким образом, вы можете использовать одну и ту же функцию для заполнения данных о новом или существующем объекте.

Скажем, у меня есть функция, которая принимает первичный ключ и массив данных, заполняет строку данными, а затем сохраняет полученную запись в базу данных.Поскольку я собираюсь заполнить объект своими данными в любом случае, получение пустого объекта обратно от метода получения может быть огромным преимуществом.Таким образом, я могу выполнять одинаковые операции в любом случае.Вы используете результат функции получения, несмотря ни на что.

Пример:

function saveTheRow($prim_key, $data) {
    $row = getRowByPrimKey($prim_key);

    // Populate the data here

    $row->save();
}

Здесь мы видим, что одна и та же серия операций манипулирует всеми записями этого типа.

Однако, если конечная цель возвращаемого значения — прочитать данные и что-то сделать с ними, я бы вернул ноль.Таким образом, я могу очень быстро определить, не были ли возвращены данные, и отобразить соответствующее сообщение пользователю.

Обычно я улавливаю исключения в своей функции, которая извлекает данные (чтобы я мог регистрировать сообщения об ошибках и т. д.), а затем возвращаю ноль прямо из улова.Для конечного пользователя обычно не имеет значения, в чем проблема, поэтому я считаю, что лучше всего инкапсулировать регистрацию/обработку ошибок непосредственно в функции, которая получает данные.Если вы поддерживаете общую кодовую базу в какой-либо крупной компании, это особенно полезно, поскольку вы можете заставить правильно регистрировать/обрабатывать ошибки даже самого ленивого программиста.

Пример:

function displayData($row_id) {
    // Logging of the error would happen in this function
    $row = getRow($row_id);
    if($row === null) {
        // Handle the error here
    }

    // Do stuff here with data
}

function getRow($row_id) {
 $row = null;
 try{
     if(!$db->connected()) {
   throw excpetion("Couldn't Connect");
  }

  $result = $db->query($some_query_using_row_id);

  if(count($result) == 0 ) {
   throw new exception("Couldn't find a record!");
  }

  $row = $db->nextRow();

 } catch (db_exception) {
  //Log db conn error, alert admin, etc...
  return null; // This way I know that null means an error occurred
 }
 return $row;
}

Это мое общее правило.До сих пор это работало хорошо.

Интересный вопрос, и я думаю, что здесь нет "права" ответ, так как это всегда зависит от ответственности вашего кода. Ваш метод знает, является ли отсутствие найденных данных проблемой или нет? В большинстве случаев ответ «нет» и именно поэтому возвращение null и разрешение вызывающей стороне его ситуации идеально.

Может быть, хороший способ отличить методы броска от методов с нулевым возвратом - это найти в вашей команде соглашение: методы, которые говорят, что они " get " что-то должно вызвать исключение, если нечего получить. Методы, которые могут возвращать нуль, могут называться по-разному, например, «Найти ...» вместо этого.

Если возвращаемый объект можно перебирать, я бы вернул пустой объект, чтобы мне не приходилось сначала проверять значение null.

Пример:

bool IsAdministrator(User user)
{
    var groupsOfUser = GetGroupsOfUser(user);

    // This foreach would cause a run time exception if groupsOfUser is null.
    foreach (var groupOfUser in groupsOfUser) 
    {
        if (groupOfUser.Name == "Administrators")
        {
            return true;
        }
    }

    return false;
}

Мне нравится не возвращать нуль из любого метода, а использовать вместо этого функциональный тип Option. Методы, которые не могут вернуть результат, возвращают пустой параметр, а не ноль.

Кроме того, такие методы, которые не могут вернуть результат, должны указывать это через свое имя. Обычно я помещаю Try или TryGet или TryFind в начале имени метода, чтобы указать, что он может вернуть пустой результат (например, TryFindCustomer, TryLoadFile и т. Д.).

Это позволяет вызывающей стороне применять различные методы, например конвейеризацию коллекции (см. конвейер сбора Мартина Фаулера) ) на результат.

Вот еще один пример, где возвращаемый Option вместо null используется для уменьшения сложности кода: Как уменьшить цикломатическую сложность: дополнительный функциональный тип

Больше мяса для измельчения: допустим, мой DAL возвращает NULL для GetPersonByID, как советовали некоторые. Что должен делать мой (довольно тонкий) BLL, если он получает NULL? Передать этот NULL и позволить конечному потребителю беспокоиться об этом (в данном случае страница ASP.Net)? Как насчет того, чтобы BLL выдал исключение?

BLL может использоваться ASP.Net и Win App, или другой библиотекой классов - я думаю, что было бы несправедливо ожидать, что конечный потребитель по сути "узнает" что метод GetPersonByID возвращает нулевое значение (я думаю, если не используются нулевые типы).

Мое мнение (для чего оно стоит) состоит в том, что мой DAL возвращает NULL, если ничего не найдено. Для НЕКОТОРЫХ ОБЪЕКТОВ это нормально - это может быть список 0: много вещей, так что отсутствие каких-либо вещей - это хорошо (например, список любимых книг). В этом случае мой BLL возвращает пустой список. Для большинства отдельных объектов (например, пользователь, учетная запись, счет-фактура), если у меня их нет, то это определенно проблема, и это является дорогостоящим исключением. Однако если пользователь извлекает пользователя по уникальному идентификатору, который был ранее задан приложением, он всегда должен возвращать пользователя, исключение составляет «правильный». исключение, как в исключительном. Конечный потребитель BLL (ASP.Net, f'rinstance) только когда-либо ожидает, что все будет просто так, поэтому вместо упаковки каждого вызова GetPersonByID в блок try-catch будет использоваться обработчик необработанных исключений.

Если в моем подходе есть явная проблема, пожалуйста, дайте мне знать, поскольку я всегда стремлюсь учиться. Как отмечали другие авторы, исключения - это дорогостоящие вещи, и «сначала проверка» подход хорош, но исключения должны быть именно такими - исключительными.

Мне нравится этот пост, много хороших советов для " это зависит от " сценарии: -)

Я думаю, что функции не должны возвращать ноль для здоровья вашей кодовой базы. Я могу придумать несколько причин:

Будет большое количество охранных предложений, обрабатывающих нулевую ссылку if (f ()! = null) .

Что такое null , это принятый ответ или проблема? Является ли null допустимым состоянием для определенного объекта? (представьте, что вы клиент для кода). Я имею в виду, что все ссылочные типы могут быть нулевыми, но должны ли они?

Наличие null будет почти всегда давать время от времени несколько неожиданных исключений NullRef по мере роста вашей кодовой базы.

Есть несколько решений, шаблон тестера или реализация типа опции из функционального программирования.

Я озадачен количеством ответов (по всей сети), которые говорят, что вам нужно два метода: " IsItThere () " метод и " GetItForMe () " метод, и поэтому это приводит к состоянию гонки. Что не так с функцией, которая возвращает null, присваивая ее переменной и проверяя переменную на Null все в одном тесте? Мой прежний код на C был приправлен

if (NULL! = (переменная = функция (аргументы ...))) {

Таким образом, вы получаете значение (или ноль) в переменной и результат сразу. Эта идиома была забыта? Почему?

Я согласен с большинством сообщений здесь, которые имеют тенденцию к null .

Я считаю, что создание пустого объекта с ненулевыми свойствами может привести к ошибкам. Например, сущность со свойством int ID будет иметь начальное значение ID = 0 , которое является полностью допустимым значением. Если при некоторых обстоятельствах этот объект будет сохранен в базе данных, это будет плохо.

Для всего, что связано с итератором, я бы всегда использовал пустую коллекцию. Что-то вроде

foreach (var eachValue in collection ?? new List<Type>(0))

это кодовый запах по моему мнению. Свойства коллекции не должны быть нулевыми.

Крайний случай - String . Многие люди говорят, что String.IsNullOrEmpty на самом деле не является необходимым, но вы не всегда можете различить пустую строку и нулевую. Более того, некоторые системы баз данных (Oracle) вообще не различают их ( '' хранится как DBNULL ), поэтому вы вынуждены обращаться с ними одинаково. Причина этого заключается в том, что большинство строковых значений поступают либо из пользовательского ввода, либо из внешних систем, в то время как ни текстовые поля, ни большинство форматов обмена не имеют разных представлений для '' и null . Таким образом, даже если пользователь хочет удалить значение, он не может сделать ничего, кроме очистки элемента управления вводом. Кроме того, различие между полями базы данных nvarchar , которые могут быть обнуляемыми и ненулевыми, более чем сомнительно, если ваша СУБД не является оракулом - обязательное поле, которое допускает '' , странно, ваш пользовательский интерфейс никогда не допустит этого, поэтому ваши ограничения не отображаются. Так что ответ здесь, на мой взгляд, обрабатывать их одинаково, всегда.

По поводу вашего вопроса об исключениях и производительности: Если вы генерируете исключение, которое вы не можете полностью обработать в логике вашей программы, вы должны в какой-то момент прервать то, что делает ваша программа, и попросить пользователя повторить то, что он только что сделал. В этом случае снижение производительности catch на самом деле является наименьшим из ваших беспокойств - необходимость спросить пользователя - это слон в комнате (что означает повторную визуализацию всего пользовательского интерфейса или отправку некоторого HTML-кода). по Интернету). Поэтому, если вы не будете следовать шаблону " Поток программы с исключениями " ;, не беспокойтесь, просто бросьте один, если это имеет смысл. Даже в пограничных случаях, таких как «Исключение валидации», производительность на самом деле не является проблемой, так как в любом случае вам придется снова спрашивать пользователя.

Асинхронный шаблон TryGet:

Для синхронных методов я считаю, что @Johann Gerell's answer - это шаблон для использования во всех случаях.

Однако шаблон TryGet с параметром out не работает с асинхронными методами.

С помощью литералов Tuple в C # 7 вы теперь можете сделать это:

async Task<(bool success, SomeObject o)> TryGetSomeObjectByIdAsync(Int32 id)
{
    if (InternalIdExists(id))
    {
        o = await InternalGetSomeObjectAsync(id);

        return (true, o);
    }
    else
    {
        return (false, default(SomeObject));
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top