Это очень хороший вопрос, так как я видел, как многие разработчики C ++ пишут ужасный код на C #.
Лучше не думать о C # как о «C ++ с более приятным синтаксисом». Это разные языки, которые требуют разных подходов в вашем мышлении. C ++ заставляет вас постоянно думать о том, что будет делать процессор и память. C # не так. C # специально разработан таким образом, чтобы вы не думали о процессоре и памяти, а вместо этого думали о бизнес-сфере, для которой вы пишете .
Один из примеров этого, который я видел, состоит в том, что многие разработчики на C ++ хотели бы использовать циклы, потому что они быстрее, чем foreach. Обычно это плохая идея в C #, поскольку она ограничивает возможные типы перебираемой коллекции (и, следовательно, возможность повторного использования и гибкость кода).
Я думаю, что лучший способ перенастроить C ++ на C # - это попробовать подойти к кодированию с другой точки зрения. Сначала это будет сложно, потому что с годами вы будете полностью привыкнуть использовать поток «что делает процессор и память» в вашем мозгу для фильтрации кода, который вы пишете. Но в C # вместо этого вы должны думать об отношениях между объектами в бизнес-сфере. «Что я хочу сделать», а не «что делает компьютер».
Если вы хотите что-то сделать со всем в списке объектов, вместо записи цикла for в списке, создайте метод, который принимает IEnumerable<MyObject>
и использует foreach
цикл.
Ваши конкретные примеры:
Управление временем жизни ресурсов, которые требуют детерминированной очистки (например, файлов). Это легко использовать в руках, но как правильно его использовать, когда право собственности на ресурс передается [... между потоками]? В C ++ я просто использовал бы общие указатели и позволял бы позаботиться о «сборке мусора» как раз в нужное время.
Вы никогда не должны делать это в C # (особенно между потоками). Если вам нужно что-то сделать с файлом, делайте это в одном месте одновременно. Это нормально (и действительно хорошая практика) написать класс-оболочку, который управляет неуправляемым ресурсом, который передается между вашими классами, но не пытайтесь передавать файл между потоками и иметь отдельные классы для записи / чтения / закрытия / открытия его. Не делитесь правами собственности на неуправляемые ресурсы. Используйте Dispose
образец, чтобы иметь дело с очисткой.
Постоянно борется с переопределением функций для конкретных обобщений (мне нравятся такие вещи, как частичная специализация шаблонов в C ++). Должен ли я просто отказаться от любых попыток сделать какое-либо общее программирование на C #? Может быть, дженерики ограничены по назначению, и это не C # -ish, чтобы использовать их, за исключением конкретной области проблем?
Обобщения в C # разработаны так, чтобы быть обобщенными. Специализации дженериков должны обрабатываться производными классами. Зачем List<T>
вести себя по-другому, если это List<int>
или List<string>
? Все операции List<T>
являются общими и применимы к любому List<T>
. Если вы хотите изменить поведение .Add
метода в a List<string>
, то создайте производный класс MySpecializedStringCollection : List<string>
или составной класс, MySpecializedStringCollection : IList<string>
который использует обобщенный тип для внутреннего использования, но работает по-другому. Это поможет вам не нарушать принцип подстановки Лискова и по-королевски подставлять других, кто использует ваш класс.
Макро-подобная функциональность. Хотя в целом это плохая идея, для некоторых областей проблем другого обходного пути нет (например, условная оценка оператора, например, для журналов, которые должны идти только в версии Debug). Отсутствие их означает, что мне нужно поставить больше, если (условие) {...} шаблон, и это все еще не равно с точки зрения запуска побочных эффектов.
Как уже говорили другие, вы можете использовать команды препроцессора для этого. Атрибуты еще лучше. В общем, атрибуты - лучший способ справиться с вещами, которые не являются «основной» функциональностью для класса.
Короче говоря, при написании C # имейте в виду, что вы должны полностью думать о бизнес-сфере, а не о процессоре и памяти. Вы можете оптимизировать позже , если это необходимо , но ваш код должен отражать отношения между деловыми принципами , которые вы пытаетесь картой.
C#
для генерации другого кода. Вы можете прочитатьCSV
или,XML
или что вы подали в качестве ввода и сгенерироватьC#
илиSQL
файл. Это может быть более мощным, чем использование функциональных макросов.