Комментарии 22
set => _firstName = value ?? throw new ArgumentNullException(nameof(value));Лично мне больше нравилось, когда по обеим частям ?? или в тернарном операторе были совместимые типы. А теперь можно писать справа что-то без типа, чтобы просто было удобно. Это спорно. C# и так хорош синтаксисом, особой надобности в спорных фичах нет.
Я думаю они совместимы до сих пор, т.к. throw в виде выражения возвращает любой generic тип, который выводится компилятором из второй ветки оператора ?? в виду того что throw не возвращает в обычном смысле.
В F#, где всё является выражением есть похожие функции:
failwith: string -> 'a
raise: exn -> 'a
принимаем строку с описанием ошибки или объект Exception и валим выполнение программы. компилятору подсовываем любой тип какой он хочет, т.к. это уже неважно, функция нормально не вернёт.
Большинство вещей выглядят более-менее интуитивно понятными.
А вот когда выпадет исключение в linq, я честно не уверен:
Если ToList в конце — то видимо на его материализации.
А если foreach — может упасть на вычислении конкретного элемента?
А вот когда выпадет исключение в linq, я честно не уверен:
.Select(c => c.Status == Status.None
? throw new InvalidDataException($"Customer {c.Id} has no status and should not be an award recipient")
: c)
Если ToList в конце — то видимо на его материализации.
А если foreach — может упасть на вычислении конкретного элемента?
Не понял вопроса, на всякий случай уточню: а вы в курсе, что
в ToList внутри foreach?
public List<TResult> ToList()
{
var list = new List<TResult>();
foreach (TSource item in _source)
{
list.Add(_selector(item));
}
return list;
}
Был не в курсе, но и не важно это.
Меня смущает другое — когда я делаю linq операцию, она обычно отложена. Выброс исключения видимо тоже откладывается до перечисления элемента?
А что будет со всеми траснляторами в sql? Они справятся с трансляцией исключения? Смысла в этом мало =_=
Меня смущает другое — когда я делаю linq операцию, она обычно отложена. Выброс исключения видимо тоже откладывается до перечисления элемента?
А что будет со всеми траснляторами в sql? Они справятся с трансляцией исключения? Смысла в этом мало =_=
А что будет со всеми траснляторами в sql? Они справятся с трансляцией исключения?
Фреймворки вида LINQ to SQL, в отличие от LINQ методов для коллекций, используют не делегаты, а деревья выражений (expression trees), по которым строят запрос к базе. В деревьях выражений нельзя использовать throw-выражения.
Такой код не скомпилируется:
void A(Expression<Func<int, bool>> expr) {}
A(x => throw new Exception()); // [CS8188] An expression tree may not contain a throw-expression.
Также в expression'ах нет поддержки других конструкций C# 7: кортежей (tuple literals), объявлений переменных при вызове метода с out-параметром (out var)
Исключения в свойствах — зло.
Остальное — приятный сахар.
Остальное — приятный сахар.
Исключения в свойствах — зло.Почему это? ExceptionValidationRule в WPF специально для этого и существует. Чем getter/setter cвойств принципиально отличаются от методов, в которых, я надеюсь, исключения не зло?
Почему это? ExceptionValidationRule в WPF специально для этого и существует.
ExceptionValidationRule отлавливает исключения, которые не обязательно сгенерированы внутри свойства. Они могут появляться и до попытки присвоения значения. При той же конвертации.
Да и вообще, WPF и его Data Binding много чего странного привносит в архитектуру решения.
Чем getter/setter cвойств принципиально отличаются от методов, в которых, я надеюсь, исключения не зло?
Тут уже личное мнение. Технически — почти ничем не отличаются. Коцептуально как раз тем, что свойства не должны содержать никакой логики. В том числе такой, которая приводит к исключениям. В отличие от методов. Поэтому, если для изменения состояния объекта, необходимо провести какие-то дополнительные проверки, то нужно делать это методом.
Иначе мы придём к чему-то такому:
var foo = new Bar();
try
{
foo.Name = "This is my Name";
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
> Коцептуально как раз тем, что свойства не должны содержать никакой логики.
Это неожиданно. А вы это где прочитали?
Это неожиданно. А вы это где прочитали?
WPF и его Data Binding много чего странного привносит в архитектуру решенияВ точку.
свойства не должны содержать никакой логики.Судя по всему, вы путаете назначение полей и свойств. Свойства как раз для того и нужны, чтобы добавить некую «простую» логику, чего нельзя сделать для поля. Интуитивно я понимаю, что вы имели в виду. Если эта логика переиспользуется или слишком сложна (много строк или различающихся по смыслу действий?) для свойства, то ее имеет смысл вынести в отдельный (переиспользуемый) метод или даже в несколько.
В вашем примере, если Name — это свойство, при установке которого должны установится другие, то вполне ожидаемо получить исключение при ошибке парсинга или конвертации. Например, FullName может ожидать пробел и/или более одного слова, чтобы установить FirstName и LastName.
Я в целом согласен с Imbecile. В вашем примере я бы сделал FullName только с геттером, который бы бросал исключение, если FirstName или LastName не установлены (если нам надо). И отдельный метод ParseFullName.
Излишнее стремление к лаконичности — порочно. По мне, вот этот код:
чище и понятнее вот этого:
Всем известно, что в C и C++ можно писать очень кратко и очень непонятно. Только надо ли?
public ClientService(
IClientsRepository clientsRepository,
IClientsNotifications clientsNotificator)
{
if (clientsRepository == null)
{
throw new ArgumentNullException(nameof(clientsRepository));
}
if (clientsNotificator == null)
{
throw new ArgumentNullException(nameof(clientsNotificator));
}
this.clientsRepository = clientsRepository;
this.clientsNotificator = clientsNotificator;
}
чище и понятнее вот этого:
public ClientService(
IClientsRepository clientsRepository,
IClientsNotifications clientsNotificator)
{
this.clientsRepository = clientsRepository ?? throw new ArgumentNullException(nameof(clientsRepository));
this.clientsNotificator = clientsNotificator ?? throw new ArgumentNullException(nameof(clientsNotificator));
}
Всем известно, что в C и C++ можно писать очень кратко и очень непонятно. Только надо ли?
По-моему второй первый вариант кажется приятней, только если редко сталкиваетесь с оператором ??.. Я часто использую/сталкиваюсь, поэтому мне второй вариант кажется лаконичнее.
Он лаконичнее, с этим никто не спорит. Но в то же время, он дальше от обычного человеческого языка, чем первый.
Второй вариант семантически отличается от первого. В первом варианте — в случае возникновения исключений внутреннее состояние экземпляра не меняется. Тогда как во втором случае — изменяется и становится неконсистентным.
Это конечно же надо иметь в виду в случае исполнения вне конструктора.
Это конечно же надо иметь в виду в случае исполнения вне конструктора.
Второй вариант семантически отличается от первого. В первом варианте — в случае возникновения исключений внутреннее состояние экземпляра не меняется. Тогда как во втором случае — изменяется и становится неконсистентным.
А вот это верно.
Контракты должны проверяться до действий, меняющих состояние.
Это конечно же надо иметь в виду в случае исполнения вне конструктора.Да и в конструкторе тоже — что, если в нем выполняются некие «тяжелые» действия и/или с сайд эффектами, и вдруг окажется, что ничего делать не надо было, т.к. в параметрах пришел null?
(Что не отменяет того, что такие тяжелые конструкторы не следует делать.)
Вариант вида this.clientsRepository = clientsRepository ?? throw new ArgumentNullException(nameof(clientsRepository)); вполне чист и понятен.
Другое дело, что выбор примера неудачен, т.к. подобные вещи лучше делать через Code Contracts — жаль, что в System.Diagnostics.Contracts так и не стали в .NET стандартом (хотя бы де факто) и полноценной частью платформы.
К тому же, если совсем по хорошему, то тут и не Code Contracts нужны, а (Not)Nullability.
Другое дело, что выбор примера неудачен, т.к. подобные вещи лучше делать через Code Contracts — жаль, что в System.Diagnostics.Contracts так и не стали в .NET стандартом (хотя бы де факто) и полноценной частью платформы.
К тому же, если совсем по хорошему, то тут и не Code Contracts нужны, а (Not)Nullability.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Throw выражения в C# 7