Дублирование в C#?

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

CREATE TRIGGER `update_request_missions_after_insert` BEFORE INSERT ON `request_missions`
FOR EACH ROW
BEGIN
  DECLARE next_id INT;
  SELECT COALESCE(MAX(id),0) + 1 INTO next_id FROM request_missions;
  IF next_id BETWEEN 1 AND 9 THEN
    SET NEW.rm_number = CONCAT(DATE_FORMAT(CURDATE(),'%y'), '-', '00000', next_id);
  END IF;
END

Предупреждение: это страдает от состояния гонки. Например, если два сеанса вставляются в таблицу одновременно, они могут оба читать одно и то же next_id.

Также, как @ P.Salmon прокомментировал выше, результаты не определены, если next_id> 9. Я не уверен, что вы пытаетесь сделать.

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

LPAD(next_id, 6, '0')

См. Руководство по функции LPAD () . [ 1123]

Я использовал COALESCE(MAX(id),0), чтобы убедиться, что по крайней мере одно возвращаемое значение, отличное от NULL, в случае, если таблица содержит ноль строк.

Это также касается:

DATE_FORMAT(CURDATE(),'%y')

Год из двух цифр перенесется на 00 через 81 год. Именно так и была создана проблема Y2K! Я знаю, что к тому времени вы не будете работать над кодом, поэтому вам может быть все равно. Но вы всегда должны кодировать так, как будто человек, который в конечном итоге поддерживает ваш код, является жестоким психопатом, который знает, где вы живете.


Ваш новый код опубликован в другом ответе:

Это лучшее решение для обработки чисел next_id до 999 999.

CREATE TRIGGER `update_request_missions_after_insert` BEFORE INSERT ON `request_missions`
FOR EACH ROW
BEGIN
  DECLARE next_id INT;
  SELECT COALESCE(MAX(id),0) + 1 INTO next_id FROM request_missions;
  IF next_id < 1000000 THEN
    SET NEW.rm_number = CONCAT(DATE_FORMAT(CURDATE(),'%y'), '-', LPAD(next_id, 6, '0'));
  ELSE
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'RM Number has reached capacity'
  END IF;
END

Проблема состояния гонки отличается, и пока вы не используете MAX(id), чтобы найти последний идентификатор, решения не существует. Проблема в том, что у вас может быть несколько клиентов, одновременно вставляющих в таблицу. Каждый сеанс клиента будет читать одно и то же значение для MAX(id) и использовать его.

Вы должны прочитать о Расовых условиях .

Что вам действительно нужно, так это какой-то способ использования значения AUTO_INCREMENT, которое генерирует новые уникальные значения в поточно-ориентированном виде, и копирует значение в ваш rm_number.

К сожалению, нет способа сделать это в триггере. Во время триггера BEFORE INSERT новое значение AUTO_INCREMENT еще не генерируется. Во время триггера AFTER INSERT вы не можете изменить NEW.rm_number, потому что вставка уже сделана. В прошлом я писал об этом:

12
задан Even Mien 13 October 2008 в 18:12
поделиться

17 ответов

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

  1. Переменная назвала расстояния типа List<int>.
  2. Объект на "куче" типа List<int>.

Рассмотрите следующее:

Person[] coworkers = new Employee[20];

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

74
ответ дан 2 December 2019 в 02:49
поделиться

Поскольку мы увлекаются компиляторами и ошибками компилятора.

-1
ответ дан 2 December 2019 в 02:49
поделиться

Я вижу еще одну проблему с использованием var для лени как этот

var names = new List<string>();

При использовании var переменная, названная "именами", вводится как List<string>, но Вы в конечном счете только использовали бы один из интерфейсов, наследованных List<T>.

IList<string> = new List<string>();
ICollection<string> = new List<string>();
IEnumerable<string> = new List<string>();

Можно ли автоматически использовать все этого, но можно рассмотреть то, что соединяет интерфейсом с Вами, хотел использовать в то время, когда Вы написали код?

Ключевое слово var не улучшает удобочитаемость в этом примере.

0
ответ дан 2 December 2019 в 02:49
поделиться

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

Я очень предпочел бы этот (C#)

int i;

к этому (VB.NET)

Dim i as Integer

Теперь, конкретный пример, который Вы выбрали, является чем-то о.NET в целом, которая находится немного на длинной стороне, но я не думаю, что это - отказ C#. Возможно, вопрос должен быть перефразирован, "Почему код.NET таким образом подробный?"

0
ответ дан 2 December 2019 в 02:49
поделиться

Используйте var, если очевидно, что тип читателю.

//Use var here
var names = new List<string>();

//but not here
List<string> names = GetNames();

От microsofts C# программирующий руководство

Ключевое слово var может также быть полезным, когда определенный тип переменной утомителен для ввода на клавиатуре, или очевиден, или не добавляет к удобочитаемости кода

1
ответ дан 2 December 2019 в 02:49
поделиться

C# определенно становится менее подробным после добавления функциональной поддержки.

1
ответ дан 2 December 2019 в 02:49
поделиться

Это только "избыточно" при сравнении его с динамически типизированными языками. Это полезно для полиморфизма и ошибок открытия во время компиляции. Кроме того, это делает код auto-complete/intellisense легче для Вашего IDE (при использовании одного).

2
ответ дан 2 December 2019 в 02:49
поделиться

Исторический артефакт статического контроля типов / синтаксис C; сравните пример Ruby:

distances = []
1
ответ дан 2 December 2019 в 02:49
поделиться

Мог также сделать:

var distances = new List<int>();
3
ответ дан 2 December 2019 в 02:49
поделиться

Улучшения компилятора для C# 3.0 (который соответствует.Net 3.5) устраняют часть этого вида вещи. Таким образом, Ваш код может теперь быть написан как:

var distances = new List<int>();

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

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

2
ответ дан 2 December 2019 в 02:49
поделиться

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

вместо наличия

Расстояния списка; расстояния = новый Список ();

c# позволяет Вам поместить их на одну строку.

Одна строка говорит, что "Я буду использовать переменную, названную расстояниями, и это будет иметь список типов". Другая строка говорит, "Выделяют новый Список и вызывают конструктора без параметров".

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

1. Выделяет объявление переменной от объектного выделения. Разрешение:

IEnumerable<int> distances = new List<int>();
// or more likely...
IEnumerable<int> distances = GetList();

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

Оба из них требуются для записи программного обеспечения? Нет. Существует много языков, которые не делают этого и/или расходятся во многих других точках.

"Доктор! причиняет боль, когда я делаю это!" - "Больше не делают этого"

Если Вы находите, что не нуждаетесь или хотите вещи, которые c# дает Вам, попробуйте другие языки. Даже если Вы не используете их, зная, что другие могут дать Вам огромное повышение того, как Вы приближаетесь к проблемам. Если Вы действительно используете один, большой!

Так или иначе можно найти, что достаточно перспективы позволяет себе говорить, что "Мне не нужна строгая статическая проверка типа, осуществленная c# компилятором. Я буду использовать Python", вместо того, чтобы гореть c# как слишком избыточный.

4
ответ дан 2 December 2019 в 02:49
поделиться

Вы могли всегда говорить:

 var distances = new List<int>();
10
ответ дан 2 December 2019 в 02:49
поделиться

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

К счастью, Eric Lippert пишет об этом намного более красноречиво, чем я: http://csharpindepth.com/ViewNote.aspx?NoteID=63 http://csharpindepth.com/ViewNote.aspx?NoteID=61

9
ответ дан 2 December 2019 в 02:49
поделиться

Поскольку объявление типа не обязательно имеет какое-либо отношение к инициализации его.

Я могу объявить

List<int> foo; 

и оставьте это быть инициализированными позже. Где дублирование затем? Возможно, это получает значение от другой функции как BuildList ().

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

4
ответ дан 2 December 2019 в 02:49
поделиться

Что такое redudant об этом?

List<int> listOfInts = new List<int>():

Переведенный в английский язык: (РЕДАКТИРОВАНИЕ, очищенное немного для разъяснения)

  • Создайте указатель списка типов <интервал> и назовите его listofInts.
  • listOfInts теперь не создается, но его просто ссылочный указатель, указывающий нигде (на пустой указатель)
  • Теперь, создайте объект списка типов <интервал> на "куче" и возвратите указатель на listOfInts.
  • Теперь listOfInts указывает на Список <интервал> на "куче".

Едва ли подробный, когда Вы думаете о том, что это делает.

Конечно, существует альтернатива:

var listOfInts = new List<int>();

Здесь мы используем вывод типа C#, потому что Вы присваиваете ему сразу, C# может выяснить то, что вводит Вас, хотят создать объектом, просто созданным в "куче".

Чтобы полностью понять, как CLR обрабатывает типы, я рекомендую читать CLR Через C#.

15
ответ дан 2 December 2019 в 02:49
поделиться

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

Теперь с выводом типа с помощью ключевого слова var, то дублирование может быть устранено. Компилятор достаточно умен для понимания этого. Следующий C++ также имеет автоматическое ключевое слово, которое делает то же самое.

Главная причина они представили var, тем не менее, была для анонимных типов, которые не имеют никакого имени:

var x = new {Foo = Bar, Number = 1};
2
ответ дан 2 December 2019 в 02:49
поделиться

Во многих ответах на этот вопрос авторы думают как составители или апологеты. Важное правило хорошего программирования: Не повторяйся!

Предотвращение этого ненужного повторения является явной целью дизайна Go, например:

Заикание ( foo.Foo * myFoo = new (foo.Foo) ) уменьшено путем получения простого типа с помощью конструкции : = declare-and-initialize.

0
ответ дан 2 December 2019 в 02:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: