, C# переводит ключевое слово урожая в конечный автомат во время компиляции. VB.NET не имеет ключевого слова урожая, но оно действительно имеет свой собственный механизм для того, чтобы безопасно встроить состояние в функции, которая не легко доступна в C#.
ключевое слово C# static
обычно переводится в Visual Basic с помощью Shared
ключевое слово, но существует два места, где вещи становятся сбивающими с толку. Каждый - это, статическим классом C# является действительно Модуль в Visual Basic, а не Общем классе (Вы думали бы, что они позволили Вам кодировать его так или иначе в Visual Basic, но noooo). Другой то, что VB.NET действительно имеет его собственное Static
ключевое слово. Однако Static
имеет различное значение в VB.NET.
Вы используете Static
ключевое слово в VB.NET для объявления переменной в функции, и когда Вы делаете переменная сохраняет свое состояние через вызовы функции. Это отличается, чем просто объявление частного статического участника класса в C#, потому что статический функциональный участник в VB.NET, как гарантируют, также будет ориентирован на многопотоковое исполнение, в котором компилятор переводит его для использования класса Монитора во время компиляции.
Итак, почему запись все это здесь? Ну, должно быть возможно создать допускающий повторное использование дженерик Iterator
класс (или Iterator(Of T)
в VB.NET). В этом классе Вы реализовали бы конечный автомат, используемый C#, с Yield()
и Break()
методы, которые соответствуют ключевым словам C#. Тогда Вы могли использовать статический экземпляр (в смысле VB.NET) в функции так, чтобы он мог в конечном счете сделать в значительной степени то же задание как C# yield
приблизительно в том же объеме кода (отбрасывание класса implemenation самого, так как это было бы бесконечно допускающим повторное использование).
я не заботился достаточно об Урожае для попытки его сам, но это должно быть выполнимым. Однако это также совсем не тривиально, как член команды C# Eric Lippert называет это" самое сложное преобразование в компиляторе ".
я также приехал для веры, так как я записал первый проект этого более чем год назад, что это не действительно возможно значимым способом до Visual Studio, 2010 выходит, поскольку это потребовало бы отправки нескольких лямбд к классу Итератора, и так быть действительно практичными нам нужно .NET 4 поддержка многострочных лямбд.
Я всегда предпочитаю решение без дублирования кода. Даже если поначалу сложнее понять сложную архитектуру, преимущества обслуживания более чем перевешивают кривую обучения.
Excellent question; the generic answers may not fit for your situation. There are many factors decides your choice
These are some of the crucial factors decides your choice. In my experience I realize duplicate business logic (middle tier) code is not good practice but the presentation layer can have duplicate codes.
When I am writing this I remember the article "Does Slow Growth Equal Death". Writing quality and non-duplicate code might take time but that shouldn't be a bottleneck for your business.
Основная причина того, почему обобщенные типы трудно читать, заключается в том, что они незнакомы неопытным программистам. Это означает, что необходимо проявлять большую осторожность при выборе именования и документации, чтобы обеспечить ясность.
Чрезвычайно важно, чтобы такие базовые классы имели правильные имена. Дизайнер может пожелать тщательно обсудить это с коллегами, прежде чем выбирать имена.
Прежде чем дать свой ответ, я хотел бы увидеть некоторый пример кода, чтобы понять, в чем вопрос на самом деле.
Ожидая этого, я считаю, что если ваш код встроен в большинство разумные принципы объектно-ориентированного программирования (такие как каждый класс делает только одно и только одно ), не должно быть никакого дублирования кода. Конечно, можно сходить с ума с абстракциями и т. Д., Которые в конечном итоге создают огромную кучу бесполезных классов, но я не думаю, что здесь проблема.
Зависит от ряда факторов:
Так что мой ответ, возможно ...
Нет. Ни одна из этих ситуаций не приемлема. Пишите его с помощью универсальных шаблонов, но настолько сложными, насколько это необходимо.
Не дублируйте код; вам придется дважды исправлять ошибки, дважды добавлять улучшения, дважды писать комментарии, дважды писать тесты. Каждая создаваемая вами строка кода - это небольшое бремя, которое вам придется нести, пока вы работаете с этой кодовой базой; минимизируйте свое бремя.
Это призыв к суждению. Большинство программистов слишком много дублируют код, и я думаю, что это приводит к мнению увлеченных разработчиков, что искоренение дублирования - абсолютное благо, но это не так. Сделать ваш код легко читаемым должно быть приоритетом, а устранение дублирующегося кода обычно хорошо для читабельности, но не всегда.
Кроме того, я бы не стал использовать коммерчески ценный код как место для использования функций незнакомого языка для цель их изучения. Создайте для этого отдельные учебные проекты. Вы же не хотите, чтобы вас вызывали на работу в нерабочее время для исправления ошибок, вызванных чрезмерным увлечением дженериками или любыми другими функциями.
Бывают крайние случаи, когда вы предотвращаете дублирование кода за счет сложного метапрограммирования (не такая большая проблема для Java) или чрезмерного использования отражения, и в этих нескольких случаях я бы предпочел разрешить дублирование. Это редко. Пока код остается понятным для достаточно опытного разработчика, который не является вами, я бы пошел на устранение дублирования.
Я встречал ситуации, когда в команду входили один или два опытных разработчика и куча новичков, где новички пытаются предотвратить использование подходов к кодированию, которые они не понимают с первого взгляда. Этому нужно сопротивляться.
Основная причина избежать дублирования кода - ремонтопригодность. Если сегмент кода появляется в нескольких местах, когда придет время обновлять, вы должны не забыть изменить его везде . Если вы забудете изменить один экземпляр, это может вызвать большие проблемы, которые вы можете не заметить сразу.
Хотя обе цели являются хорошими, я считаю, что удобочитаемость является абсолютным первым требованием для наличия поддерживаемой кодовой базы. Я всегда предпочел бы простоту, удобочитаемость и удобство обслуживания полному исключению дублирования кода.
Избегать дублирования кода - всегда хорошо. Единственное, от чего вам нужно остерегаться, - это Преждевременное обобщение .
Не нужно спешить, если вы получите пару похожих фрагментов кода. Это нормально - сидеть сложа руки, пока вы не выработаете хорошую модель.
Даже если вы позволите несколько примеров того, что вам нужно обобщить, может быть нормально, особенно, когда вещи немного более сложные и / или открытые. Будет проще сделать обобщение, если у вас есть 3-5+ примеров, а не один или два.
Я не понимаю, как термин "дженерики" связан с вашим вопросом. Тривиально и очевидно неправильно иметь отдельные классы для представления CollectionOfFoo и CollectionOfBar, так что это не может быть тем, о чем вы спрашиваете.
Вероятно, вам придется предоставить пример для каждой точки зрения, но вы ' Я все еще, вероятно, закрою за субъективность.
Рекомендация: Если код короткий, продублируйте его дважды, но не более того. .
Итак, если у вас есть очень похожие фрагменты кода, скопированные / вставленные в 3 разных места, подумайте о рефакторинге.
Имейте в виду, что рефакторинг не делает ' t автоматически означает усложнение кода. Примите во внимание следующее:
class IntStack
{
public int value;
public IntStack next;
}
class StringStack
{
public String value;
public StringStack next;
}
class PersonStack
{
public Person value;
pubilc PersonStack Next;
}
Каждый раз, когда вам нужен стек для нового типа данных, вам нужно написать новый класс. Дублирование кода работает нормально, но предположим, что вы хотите добавить новый метод, может быть, метод «Push», который возвращает новый стек? Хорошо, теперь вы вынуждены добавить его в миллионы разных мест. Или вы можете использовать общий стек объектов, но тогда вы потеряете безопасность типов. Обобщения упростят архитектуру:
class Stack<T>
{
public T value;
public Stack<T> next;
}
Круто!
Хорошо, как насчет этого примера:
class Logger
{
int logtype;
public Logger(int logtype) { ... }
public void Log(string text)
{
if (logtype == FILE) { ... }
elseif (logtype == DATABASE) { ... }
elseif (logtype == CONSOLE) { ... }
}
public void Clear()
{
if (logtype == FILE) { ... }
elseif (logtype == DATABASE) { ... }
elseif (logtype == CONSOLE) { ... }
}
public void Truncate(int messagesToTruncate)
{
if (logtype == FILE) { ... }
elseif (logtype == DATABASE) { ... }
elseif (logtype == CONSOLE) { ... }
}
}
Хорошо, поэтому каждый раз, когда вы добавляете метод, вы должны проверять, какой тип регистратора вы используете. Болезненный и склонный к ошибкам. Обычно вы выделяете интерфейс (возможно, с помощью методов Log, Clear и Truncate), а затем создаете три класса (FileLogger, DatabaseLogger, ConsoleLogger).
Больше классов = больше архитектуры. Это легче или сложнее поддерживать в долгосрочной перспективе? В этом примере я бы сказал, что код теперь легче поддерживать, но YMMV.
Сравните это с нормализацией в реляционных базах данных - вы, вероятно, захотите одно место, где находится какая-то функция или данные, а не много мест. Это имеет большое значение с точки зрения ремонтопригодности и способности размышлять о вашем коде.
Обычно единственные причины для дублирования кода - это преодоление слабой языковой системы шаблонов / макросов / универсальных шаблонов или для оптимизации, где есть разные низкие имена функций уровня, которые обрабатывают разные типы.
В C ++, с которым, как вы отметили, вы не работаете, система шаблонов позволяет создавать типы и функции без дополнительных затрат со специализацией доступен для «настройки» сгенерированного кода для определенных параметров типа. В Java нет ничего подобного, что устраняет возможность исключения как общего, так и конкретного выбора, доступного в C ++.
В Common Lisp можно использовать макросы и макросы компилятора для создания кода, аналогичного шаблонам C ++, где можно настраивать базовые случаи. для определенных типов, что приводит к различным расширениям кода.
В Java я бы возражал против универсального кода только тогда, когда внутренние циклы использовали числовые типы. Оплата затрат на упаковку и распаковку числовых типов в универсальном коде неприемлема в этих случаях, если только ваш профилировщик не убедит вас, что компилятор или HotSpot были достаточно умен, чтобы отказаться от упаковки.
Что касается удобочитаемости, что ж, сделайте свой код наиболее подходящим. модель и вызов, который нужно решить вашим коллегам. Предложите обучить тех, кому трудно это читать. Поощряйте их проверять его на наличие дефектов. Если они найдут,