.NET und C# ohne Web?
навскидку: вот нужна мне функция, которая выдаёт корни квадрантного уравнения
Ну очевидно, я бы сказал, что возврат IEnumerable был бы лучше, т.к. можно было бы объявить общий интерфейс для квадратного уравнения, кубического, уровнения любой степени, дифференциального уравнения, системы уравнений итд. В случае с кортежем такой гибкости нет.
Или функция, которая выдаёт немецкую календарную неделю: kw, year переданной даты.
Не совсем понял, что ты тут предлагаешь и зачем такая функция может понадобиться, когда есть DateTime, а расчет KW можно прикрутить exstension методом. Собственно говоря, решение вычислась две разных задачи в одной функции - не самое лучше решения с точки зрения дизайна ;)
Просто в Try- методах эксепшены обрабатываются.
-----
Какая разница что и как там внутри? Нет выброса исключений из функции и точка.
Собственно говоря, вопрос в том, что является ошибкой.
------
Не вопрос.
Вопросом было наличие реф/оут параметра.
В зависимости от задачи невозможность распарсить значение может быть как ошибкой, так и штатной ситуацией.
-----
Ну и?
int? parsedValue = int.Parse(myString);
надо тебе проверить как распарсилось - проверяй
if(!parsedValue.HasData) { /*obrabotka oshibki */}
Зачем городить кучу хрени со сложностями?
Какая разница что и как там внутри? Нет выброса исключений из функции и точка.
Разница в том, что считать ошибкой. В случае ошибки функция должна выбрасывать исключение. Если в случае ошибки функция возвращает null, то нельзя сказать, является ли null нештатной ситуацией.
if(!parsedValue.HasData) { /*obrabotka oshibki */}
Зачем городить кучу хрени со сложностями?
Все это мило, но код превратится во что-то слабо читаемое, если тебе надо будет распарсить десяток строк:
Сравни твой вариант:
int? parsedValue = int.Parse (strVal1); if(!parsedValue.HasData) return null; someObject.Val1 = parsedValue.Value; parsedValue = int.Parse (strVal2); if(!parsedValue.HasData) return null; someObject.Val2 = parsedValue.Value; parsedValue = int.Parse (strVal3); if(!parsedValue.HasData) return null; someObject.Val3 = parsedValue.Value; parsedValue = int.Parse (strVal4); if(!parsedValue.HasData) return null; someObject.Val4 = parsedValue.Value; parsedValue = int.Parse (strVal5); if(!parsedValue.HasData) return null; someObject.Val5 = parsedValue.Value; return someObject;
и вариант с исключением:
try { someObject.Val1 = int.Parse(strVal1); someObject.Val2 = int.Parse(strVal2); someObject.Val3 = int.Parse(strVal3); someObject.Val4 = int.Parse(strVal4); someObject.Val5 = int.Parse(strVal5); return someObject; } catch (Exception ex) { logger.Error ("Can't parse value", ex); return null; }
честно говоря, за твой вариант с nullable int'ом отрывать руки. ИМХО :)
Exception - это ошибка
Ну скажем не ошибка, а нерабочее состояние. Состояние, в котором продолжение работы невозможно. Я проверил входные параметры и установил, что с такими параметрами считать невозможно. Я еще не сделал ошибку, не влез в расчеты. Это стратегия обработки исключительного состояния, которая позволяет обрабатывать такое состояние сразу, ценрализованно и не тащитьсообщение о нерабочем состоянии через весь стек обратно.
А то, что наличие оут-параметров нарушало школьное определение функции тебе не мешало?
Да мне пофиг на мхом поросшие определения функции. Кому надо, пусть возвращает из функции всегда только одно значение, городит для этого спецкласс и думает, что хороший мальчик и остался в той же парадигме, хотя на самом деле просто прикрыл фиговым листочком свои текущие как мартовская кошка абстракции. Тем более, что в шарпе не функции, а методы. А народу надо уже много лет возвращать несколько параметров за раз, а аут-параметры были неудобным костылём. Возврат кортежа удобнее. Может, можно и ещё улучшить, но и это уже прогресс.
В вопросе возврата чего-то из функции меня больше интересует где будет размещен результат - куча? стек?
Если программист должен постоянно задумываться о куче и стеке, когда что-то из метода возвращает, он просто напрасно тратит время и забивает голову. Языки высокого уровня были придуманы, чтобы больше времени уделять задачам, а не деталям реализации самого языка. Кому охота постоянно так задумываться и двигать битики ручками, экономя такты процессора - добро пожаловать в плюсы и чистый Си. Узкие участки оптимизируются вплоть до ассемблера, но только узкие, а не на каждый возврат из функции заморачиваться.
Хотя еще удобнее было бы просто сделать возврат класса/интерфейса
-----
Ну так нормальные прогеры так и писали.
Так писали хорошие мальчики, чтобы их не заругали, что они отступают от парадигм седобородых дядечек. Хотя на самом деле они просто городили спагетти-костыли.
Про именованные не знал. Так это конечно удобно. Но работает начиная с .Net 4.7.
С 17 года работает - каменный век по меркам веба (в котором каждый год рождается один и умирает другой фреймворк, который родился 3-4 года назад).
.net - What are the correct version numbers for C#? - Stack Overflow
я Вам уже говорил когда-то: рассылайтесь веерно и не ждите окончания обучения, за ними начнутся другие курсы, а потом ещё одни
Вы когда начнёте работать, увидите, каких дятлов тут иногда за кодеров держат и будет обидно за упущенное время
Я уже начал.
Дятлы везде есть. Я тоже в некотором смысле дятел. Я на интервью всегда заваливался, когда выдавали список из подобных вопросов
Каверзные вопросы по C# / Habr
Там народ в комментах тоже признаётся, что далеко не всё ответить может, хотя все при работе и деньгах. Приводил в пример видос, где сеньор тоже на некоторые подобные вопросы не отвечает - они там поржали над этим и сеньор пошёл дальше получать свою сеньорскую зарплату. А проваливший собес джун пошёл дальше рассылать веером бевербунги.
Я не знаю как оно там в вебе, а у меня на работе среда разработки Visual Studio 2015 и .Net 4.0. И переход на более новую версию дот нета максимально оттягивается.
Да и вообще, в реальной жизни приходится больше работать с легаси кодом, чем писать что-то новое.
TСircumference circumference = TCalculator.CalculateCircle(circle);
Эмм, интерфейс принимает данные? У нас, вроде, по всем шаблонам и абстракциям интерфейс не должен данные описывать? Тут лучше абстракный базовый тип подошёл бы
Эмм, интерфейс принимает данные
Если я правильно понимаю, то возвращается не интерфэйс, а обьект конкретного класса, имплементирующегo этот интерфэйс. Разница в том, что интерфэйс это соглашение о использовании. И, допустим в этом интерфэйсе декларированы геттеры, возвращающие что то. Что конкретно они возвращают - за это отвечает конкретный класс. А интерфейс только гарантирует нам, что они есть.
if(int.TryParse(strData, out int age)) { Console.WriteLine($"Age:{age}"); }
У вас пропущено объявление age. В реальности оно выглядит так
int age = 0; if(int.TryParse(strData, out int age)) { Console.WriteLine($"Age:{age}"); }
Мой вариант с методом Parse (буде такой существовал), который returns "bool parsed" and "int age", when parsing was successful. А помещать сложные выражения во всяких проверках, типа if, for и т.д. всегда было плохой практикой.
var parseRes = int.Parse(strData); // returns "bool parsed" and "int age", when parsing was successful if(parseRes.parsed) { Console.WriteLine($"Age:{parseRes.age}"); }
Не можешь прочитать - кидай эксепшен.
-----
Кидай эксептион, лови эксептион, обрабатывай эксептион...
Можно, но меньше кода не станет.
Вместе с тем - есть нуллабле типы - не можешь - верни нулл и не парься...
Это известная проблема.
Ты проверяешь данные в коде в разных условных операторах и свичах, ты кидаешь эксепшен при неправильным данным и обрабатываешь эксепшен (это второй уровень проверок), ты пишешь юнит тесты (это третий уровень проверок)... А кто будет проверять юнит тесты? Существуют ли тесты для юнит тестов?
но код превратится во что-то слабо читаемое, если тебе надо будет распарсить десяток строк
-----
Правда? А если написать нормально?
someObject.Val1 = int.Parse(strVal1); someObject.Val2 = int.Parse(strVal2); someObject.Val3 = int.Parse(strVal3); someObject.Val4 = int.Parse(strVal4); someObject.Val5 = int.Parse(strVal5); if(!someObject.HasAllValues) logger.Error ("Can't parse value");
Думаю, что с трай-версиями ты сам все напишешь и порадуешся.
В случае ошибки функция должна выбрасывать исключение.
-----
Не должна, а может.
А может и не выбрасывать. Есть еще по крайней мере пара способов сообщить об ошибке.
Если в случае ошибки функция возвращает null, то нельзя сказать, является ли null нештатной ситуацией.
-----
Ты пытаешься сказать что int?.HasValue
не дает тебе достаточно информации чтобы понять было значение получено и присвоено или это не получилось?
Самому не смешно?
Мой вариант с методом Parse (буде такой существовал), который returns "bool parsed" and "int age", when parsing was successful.
Ну только "age" - слишком специализированное название. Ты же не будешь писать кажный раз новую имплементацию int.Parse(), когда тебе надо будет получить порядковый номер, количество знаков, количество детей итд
А в остальном, возможно когда-нибудь MS и добавит такую функцию и .Net. Но будь уверен, что в ближайшее десятилетие вариант с out никуда не уйдет.
А то будет проверять юнит тесты? Существуют ли тесты для юнит тестов?
Юнит-тест это метод, который проверяет условия. Мы что то делаем, потом проверяем результат сделанного. Цель - проверить написанный КОД. Юниттесты проверять не надо. Они испольняются каждай раз на бильдсервере и гарантируют соответствие кода определенным критериям. Не правильности кода, а именно соответствии критериям, установленным автором тестов.
ты кидаешь эксепшен при неправильным данным и обрабатываешь эксепшен (это второй уровень проверок)
Это не проверка КОДА. Это проверка данных. И не только данных. Так что это не второй уровень, это совсем другой уровень. Программа обрабатывает данные и иногда не может этого сделать. Это и есть исключительная ситуациq