Архив за месяц: Январь 2019

Просмотр получающегося результата при верстке в Visual Studio Code

Сегодня пробегая мимо, Саша показал как в Visual Studio Code смотреть что получается в процессе верстки. Я сильно сомневаюсь, что я буду этим заниматься регулярно, а склероз ведь не дремлет, да и вдруг кому еще пригодится. В общем, велком.

Что нам нужно:
1. Сама Visual Studo Code
2. Установленный npm. У меня он установился вместе с node.js.

Поехали. Создаем папку и выбираем ее в Visual Studio Code. Добавляем в нее index.html и все что там нам нужно. У меня это получилось вот так:

Открываем консоль (Ctrl+~) и набираем npm init
и отвечаем на вопросы инициализатора. Я на все вопросы отвечал Enter. Эта команда выполняется один раз, чтобы сгенерировать файл package.json Этот свеже сгенерированный файл нам надо немного поправить. Находим элемент scripts и заменяем в нем имеющуюся строку
"test": "echo \"Error: no test specified\" && exit 1"
На строку запуска нашего приложения. test заменяем на что угодно, это имя будет использоваться для указания при запуске, а вот параметр заменяем на parcel index.html -p 8080.  Где parcel - упаковщик (и не только), index.html это то что он будет запускать, -p 8080 - на каком порту будет доступен локальный веб-сервер запущенный parcel-ом. Должно получится вот так:

Осталось буквально два шага. Нам этот самый parcel надо установить. В консоли отдаем команду:

Как гласит девиз с сайта parcel-а: "упаковщик для веб-приложений без настроек".
Все, запускаем. Набираем в консоли npm run <и имя параметра из блока scripts>. У меня это start, поэтому полностью команда будет: npm run start

Все, по адресу http://localhost:8080 доступно то, что у нас получается при запуске нашего html. parcel весьма умный, достаточно внести изменение в html или css и сохранить их, как сразу в браузере обновляется страница:
Остановить веб сервер можно нажатием Ctrl+C.

P.s. Саша, спасибо :)
P.p.s. Опечатку в коде с первого скриншота увидел только после запуска :( Код поправил, скриншот - нет.

Просмотр получающегося результата при верстке в Visual Studio Code

Сегодня пробегая мимо, Саша показал как в Visual Studio Code смотреть что получается в процессе верстки. Я сильно сомневаюсь, что я буду этим заниматься регулярно, а склероз ведь не дремлет, да и вдруг кому еще пригодится. В общем, велком.

Что нам нужно:
1. Сама Visual Studo Code
2. Установленный npm. У меня он установился вместе с node.js.

Поехали. Создаем папку и выбираем ее в Visual Studio Code. Добавляем в нее index.html и все что там нам нужно. У меня это получилось вот так:

Открываем консоль (Ctrl+~) и набираем npm init
и отвечаем на вопросы инициализатора. Я на все вопросы отвечал Enter. Эта команда выполняется один раз, чтобы сгенерировать файл package.json Этот свеже сгенерированный файл нам надо немного поправить. Находим элемент scripts и заменяем в нем имеющуюся строку
"test": "echo \"Error: no test specified\" && exit 1"
На строку запуска нашего приложения. test заменяем на что угодно, это имя будет использоваться для указания при запуске, а вот параметр заменяем на parcel index.html -p 8080.  Где parcel - упаковщик (и не только), index.html это то что он будет запускать, -p 8080 - на каком порту будет доступен локальный веб-сервер запущенный parcel-ом. Должно получится вот так:

Осталось буквально два шага. Нам этот самый parcel надо установить. В консоли отдаем команду:

Как гласит девиз с сайта parcel-а: "упаковщик для веб-приложений без настроек".
Все, запускаем. Набираем в консоли npm run <и имя параметра из блока scripts>. У меня это start, поэтому полностью команда будет: npm run start

Все, по адресу http://localhost:8080 доступно то, что у нас получается при запуске нашего html. parcel весьма умный, достаточно внести изменение в html или css и сохранить их, как сразу в браузере обновляется страница:
Остановить веб сервер можно нажатием Ctrl+C.

P.s. Саша, спасибо :)
P.p.s. Опечатку в коде с первого скриншота увидел только после запуска :( Код поправил, скриншот - нет.

PlanUML в Visual Studio Code. Диаграммы классов


В предыдущей статье инструкция что устанавливать и как начать работать. Сегодня поговорим про нотацию используемую в PlantUML для построения диаграмм классов. Напоминаю, что диаграмма классов (англ. Static Structure diagram) это структурная диаграмма нотации UML, демонстрирующая общую структуру иерархии классов системы, их кооперацию, атрибуты (поля), методы, интерфейсы и взаимосвязи между ними. Широко применяется не только для документирования и визуализации, но также для конструирования посредством прямого или обратного проектирования.
Итак, начинаем.

Задание класса

Класс и его элементы в PlantUML можно задать двумя способами: указав имя класса и через
двоеточие член класса или указав перед именем ключевое слово class:
Первый способ избыточен (нам для каждого свойства придется указывать к какому классу оно относится), да и когда мы хотим промоделировать отношения классов без их внутреннего устройства - неприменим. Поэтому далее я буду использовать нотацию с применением ключевого слова class. Для того чтобы редактору дать понять какие члены относятся к классу используются фигурные скобки. Дальше редактор определяет данные или метод находятся перед ним на основе круглых скобок. Пусть у нас есть самолет, который умеет взлетать, и у него есть некоторая коллекция двигателей. Текст такой диаграммы может иметь вид:
@startuml Example
class Plane {
Engines : Engine[1..*]
TakesOff()
}

class Engine {

}
@enduml
В редакторе такому коду будет соответствовать следующая диаграмма:
Это последняя картинка, когда я делаю скриншот с Visual Studo Code, дальше буду показывать текст разметки и результирующую диаграмму.

Члены класса

Как я написал выше, методы и поля PlantUML отличает по круглым скобкам. Для задания модификатора доступа используются те же значки, что и в нотации UML, по умолчанию, они заменяются значками:
Т.е. мы можем задать для нашего самолета, что двигатели являются приватными, запуск двигателей доступен в потомках, техобслуживание является доступным только в рамках сборки, а команда на взлет - публичной:
class Plane {
-Engines : Engine[1..*]
#StartEngine(int index)
~CarryOutMaintenance()
+TakesOff()
}

В этом случае диаграмма будет выглядеть вот так:

Если лень запоминать значки, то можно вернуть отображение к стандартной UML нотации, для этого достаточно добавить в файл строку:
skinparam classAttributeIconSize 0

После этого, отображение вернется к стандартным значкам UML:

Кроме модификаторов доступа можно как и в UML помечать статические члены класса (подчеркнутые) и абстрактные (выделяются курсивом). Для этого используются ключевые слова static и abstract указываемые перед именем члена. Давайте добавим статическую переменную Count для хранения общего количества самолетов и абстрактный метод Fly:
class Plane {
-Engines : Engine[1..*]
{static} -Count : int
#StartEngine(int index)
~CarryOutMaintenance()
{abstract} +Fly()
+TakesOff()
}

Вот так это будет выглядеть на диаграмме:

Абстрактные классы и интерфейсы

Для отображения абстрактных классов и интерфейсов, что логично, используются ключевые слова abstract и interface:
interface IPlane {
+Fly()
+TakesOff()
}

abstract class BasePlane {
{abstract} #StartEngine(int index)
{abstract} +Fly()
+TakesOff()
}

Отображаться эти элементы будут аналогично классам, только будет отличаться буква перед именем класса и имя класса будет курсивом:

Связи

1. Обобщение, оно же - наследование. Изображается стрелкой с треугольником на конце. Для задания связи между объектами в PlantUML применяется синтаксис состояний из имен двух элементов диаграммы и стрелки между ними. Для треугольной стрелки со сплошной линией отношение будет заданно следующим образом:
BasePlane <|-- Plane

Внешний вид такой связи на диаграмме:

2. Реализация - классом некоторого интерфейса. Изображается как наследование, только линия пунктирная. Для задания такой линии необходимо минусы заменить на точки:
IPlane <|.. BasePlane

Выглядит связь следующим образом:

3. Зависимость - показывает, что при изменении одного класса, должен измениться и зависимый. Связь отличается от предыдущие отсутствием вертикальной черты, также обратите внимание, что направление стрелки можно задать и в противоположную сторону:
AirportTechnician ..> Plane

Выглядит:


4. Ассоциация - ссылка одного класса на другой. Изображается обычной стрелкой с названием отношения:
Person <-- span=""> Plane : Управляется

Внешний вид такой связи на диаграмме:

5. Агрегация - белее жесткое уточнение ассоциации, задающее отношение часть-целое. Причем часть может быть отделена и использована сама по себе (например, мы можем снять двигатель и переставить на другой самолет). Задается такое отношение указанием вместо стрелки латинской буквы o:
Plane o-- Engine

Выглядит:

6. Композиция - более жесткое уточнение ассоциации, задающее отношение часть-неотделимое целое. Если в предыдущем примере мы не моделируем снятие двигателя с самолета, и уничтожение самолета повлечет за собой уничтожение двигателя, в этом случае заменяем o на *:
Plane *-- Engine

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

Пример

В заключении давайте посмотрим, как будет выглядеть итератор в виде кода PlantUML и диаграммы UML соответственно.
Код:
@startuml Example

skinparam classAttributeIconSize 0

interface IEnumerable {
+IEnumerator GetEnumerator()
}

interface IEnumerator {
+object Current
+bool MoveNext()
+void Reset()
}

IEnumerable ..> IEnumerator : Создает

class Array {
+int Length
{static} +Sort(Array a)
+IEnumerator GetEnumerator()
}

Array ..|> IEnumerable

class ArrayEnumerator {

}

ArrayEnumerator ..|> IEnumerator

Array ..> ArrayEnumerator : Создает
ArrayEnumerator --> Array : Перемещается по

IEnumerable -[hidden]> IEnumerator
IEnumerable -[hidden]-> Array
IEnumerator -[hidden]-> ArrayEnumerator
@enduml

Обратите внимание на три строки перед @enduml, они позволяют задать расположение элементов относительно друг друга, я потом отдельно о этих связях расскажу, а то и так уже много получилось. Ну и внешний вид получившейся диаграммы:
Статический метод Sort добавил для примера, на самом деле у Array еще много чего еще есть, но все перечислять лень :)

PlantUML в Visual Studio Code. Диаграммы классов


В предыдущей статье инструкция что устанавливать и как начать работать. Сегодня поговорим про нотацию используемую в PlantUML для построения диаграмм классов. Напоминаю, что диаграмма классов (англ. Static Structure diagram) это структурная диаграмма нотации UML, демонстрирующая общую структуру иерархии классов системы, их кооперацию, атрибуты (поля), методы, интерфейсы и взаимосвязи между ними. Широко применяется не только для документирования и визуализации, но также для конструирования посредством прямого или обратного проектирования.
Итак, начинаем.

Задание класса

Класс и его элементы в PlantUML можно задать двумя способами: указав имя класса и через
двоеточие член класса или указав перед именем ключевое слово class:
Первый способ избыточен (нам для каждого свойства придется указывать к какому классу оно относится), да и когда мы хотим промоделировать отношения классов без их внутреннего устройства - неприменим. Поэтому далее я буду использовать нотацию с применением ключевого слова class. Для того чтобы редактору дать понять какие члены относятся к классу используются фигурные скобки. Дальше редактор определяет данные или метод находятся перед ним на основе круглых скобок. Пусть у нас есть самолет, который умеет взлетать, и у него есть некоторая коллекция двигателей. Текст такой диаграммы может иметь вид:
@startuml Example
class Plane {
Engines : Engine[1..*]
TakesOff()
}

class Engine {

}
@enduml
В редакторе такому коду будет соответствовать следующая диаграмма:
Это последняя картинка, когда я делаю скриншот с Visual Studo Code, дальше буду показывать текст разметки и результирующую диаграмму.

Члены класса

Как я написал выше, методы и поля PlantUML отличает по круглым скобкам. Для задания модификатора доступа используются те же значки, что и в нотации UML, по умолчанию, они заменяются значками:
Т.е. мы можем задать для нашего самолета, что двигатели являются приватными, запуск двигателей доступен в потомках, техобслуживание является доступным только в рамках сборки, а команда на взлет - публичной:
class Plane {
-Engines : Engine[1..*]
#StartEngine(int index)
~CarryOutMaintenance()
+TakesOff()
}

В этом случае диаграмма будет выглядеть вот так:

Если лень запоминать значки, то можно вернуть отображение к стандартной UML нотации, для этого достаточно добавить в файл строку:
skinparam classAttributeIconSize 0

После этого, отображение вернется к стандартным значкам UML:

Кроме модификаторов доступа можно как и в UML помечать статические члены класса (подчеркнутые) и абстрактные (выделяются курсивом). Для этого используются ключевые слова static и abstract указываемые перед именем члена. Давайте добавим статическую переменную Count для хранения общего количества самолетов и абстрактный метод Fly:
class Plane {
-Engines : Engine[1..*]
{static} -Count : int
#StartEngine(int index)
~CarryOutMaintenance()
{abstract} +Fly()
+TakesOff()
}

Вот так это будет выглядеть на диаграмме:

Абстрактные классы и интерфейсы

Для отображения абстрактных классов и интерфейсов, что логично, используются ключевые слова abstract и interface:
interface IPlane {
+Fly()
+TakesOff()
}

abstract class BasePlane {
{abstract} #StartEngine(int index)
{abstract} +Fly()
+TakesOff()
}

Отображаться эти элементы будут аналогично классам, только будет отличаться буква перед именем класса и имя класса будет курсивом:

Связи

1. Обобщение, оно же - наследование. Изображается стрелкой с треугольником на конце. Для задания связи между объектами в PlantUML применяется синтаксис состояний из имен двух элементов диаграммы и стрелки между ними. Для треугольной стрелки со сплошной линией отношение будет заданно следующим образом:
BasePlane <|-- Plane

Внешний вид такой связи на диаграмме:

2. Реализация - классом некоторого интерфейса. Изображается как наследование, только линия пунктирная. Для задания такой линии необходимо минусы заменить на точки:
IPlane <|.. BasePlane

Выглядит связь следующим образом:

3. Зависимость - показывает, что при изменении одного класса, должен измениться и зависимый. Связь отличается от предыдущие отсутствием вертикальной черты, также обратите внимание, что направление стрелки можно задать и в противоположную сторону:
AirportTechnician ..> Plane

Выглядит:


4. Ассоциация - ссылка одного класса на другой. Изображается обычной стрелкой с названием отношения:
Person <-- span=""> Plane : Управляется

Внешний вид такой связи на диаграмме:

5. Агрегация - белее жесткое уточнение ассоциации, задающее отношение часть-целое. Причем часть может быть отделена и использована сама по себе (например, мы можем снять двигатель и переставить на другой самолет). Задается такое отношение указанием вместо стрелки латинской буквы o:
Plane o-- Engine

Выглядит:

6. Композиция - более жесткое уточнение ассоциации, задающее отношение часть-неотделимое целое. Если в предыдущем примере мы не моделируем снятие двигателя с самолета, и уничтожение самолета повлечет за собой уничтожение двигателя, в этом случае заменяем o на *:
Plane *-- Engine

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

Пример

В заключении давайте посмотрим, как будет выглядеть итератор в виде кода PlantUML и диаграммы UML соответственно.
Код:
@startuml Example

skinparam classAttributeIconSize 0

interface IEnumerable {
+IEnumerator GetEnumerator()
}

interface IEnumerator {
+object Current
+bool MoveNext()
+void Reset()
}

IEnumerable ..> IEnumerator : Создает

class Array {
+int Length
{static} +Sort(Array a)
+IEnumerator GetEnumerator()
}

Array ..|> IEnumerable

class ArrayEnumerator {

}

ArrayEnumerator ..|> IEnumerator

Array ..> ArrayEnumerator : Создает
ArrayEnumerator --> Array : Перемещается по

IEnumerable -[hidden]> IEnumerator
IEnumerable -[hidden]-> Array
IEnumerator -[hidden]-> ArrayEnumerator
@enduml

Обратите внимание на три строки перед @enduml, они позволяют задать расположение элементов относительно друг друга, я потом отдельно о этих связях расскажу, а то и так уже много получилось. Ну и внешний вид получившейся диаграммы:
Статический метод Sort добавил для примера, на самом деле у Array еще много чего еще есть, но все перечислять лень :)

PlanUML в Visual Studio Code

В Visual Studio 2017 с удивлением обнаружил отсутствие проектов для моделирования (UML). Нет, можно запустить 2015, но держать две студии как-то не комильфо, да и при параллельном изменении диаграмм появляется проблема с потерей изменений того, кто сохранил не последним.
Озадачившись вопросом что можно использовать для построения UML диаграмм, наткнулся на PlanUML. Что это такое? Да много чего. Нотация, парсер и куча плагинов к наиболее распространенным средам разработки. Существенным достоинством данного подхода является хранение диаграмм в виде plan-text. Т.е. файл с моделью, это просто текстовый файл, при изменении файла несколькими людьми в параллели, даже если в результате коммитов он разъедется, всегда можно будет посмотреть кто и какие изменения внес и смержить их руками. Не все, к сожалению радужно. Применить PlantUML для хоть немного серьезной ArchiMate диаграммы (да, он и это умеет) не получилось. То ли я не владею дао, то ли в случаях, когда расположение элементов играет существенную роль, его применять не получится. Но не суть, мы сегодня про UML. Поэтому, устанавливаем и начинаем работать с PlantUml. Поехали.
Установка

1. В Visual Studi Code переходим в расширения и поиском находим PlantUML от jebbs-а. Ставим его.
2. Устанавливаем Java.
3. Перезагружаем компьютер.
4. Устанавливаем Graphviz.

Использование

Начнем с самого простого примера. В Visual Studio Code создаем новый файл и сохраняем его как Diagram с расширением, например, wsd.
В файле пишем:
@startuml Example
Class01 <|-- Class02
@enduml

Нажимаем Alt+D и получаем нашу UML диаграмму:

Экспорт

Открываем Command Palette (F1 или Ctrl+Shift+P) и набираем команду:
>PlantUML: Export Current Diagram

После нажатия Enter появляется набор расширений для экспорта:

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



PlantUML в Visual Studio Code

В Visual Studio 2017 с удивлением обнаружил отсутствие проектов для моделирования (UML). Нет, можно запустить 2015, но держать две студии как-то не комильфо, да и при параллельном изменении диаграмм появляется проблема с потерей изменений того, кто сохранил не последним.
Озадачившись вопросом что можно использовать для построения UML диаграмм, наткнулся на PlanUML. Что это такое? Да много чего. Нотация, парсер и куча плагинов к наиболее распространенным средам разработки. Существенным достоинством данного подхода является хранение диаграмм в виде plan-text. Т.е. файл с моделью, это просто текстовый файл, при изменении файла несколькими людьми в параллели, даже если в результате коммитов он разъедется, всегда можно будет посмотреть кто и какие изменения внес и смержить их руками. Не все, к сожалению радужно. Применить PlantUML для хоть немного серьезной ArchiMate диаграммы (да, он и это умеет) не получилось. То ли я не владею дао, то ли в случаях, когда расположение элементов играет существенную роль, его применять не получится. Но не суть, мы сегодня про UML. Поэтому, устанавливаем и начинаем работать с PlantUml. Поехали.
Установка

1. В Visual Studi Code переходим в расширения и поиском находим PlantUML от jebbs-а. Ставим его.
2. Устанавливаем Java.
3. Перезагружаем компьютер.
4. Устанавливаем Graphviz.

Использование

Начнем с самого простого примера. В Visual Studio Code создаем новый файл и сохраняем его как Diagram с расширением, например, wsd.
В файле пишем:
@startuml Example
Class01 <|-- Class02
@enduml

Нажимаем Alt+D и получаем нашу UML диаграмму:

Экспорт

Открываем Command Palette (F1 или Ctrl+Shift+P) и набираем команду:
>PlantUML: Export Current Diagram

После нажатия Enter появляется набор расширений для экспорта:

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



Цитата дня


Есть два метода создания программного обеспечения. Один из них — сделать программу настолько простой, что, очевидно, в ней нет недостатков. И другой, сделать приложение настолько сложным, что в нем невидно явных недостатков.

 -- T. Hoare

P.s. Да, Quick Sort был разработан сэром Чарльзом Энтони Ричард Хоар (Charles Antony Richard Hoare или Tony Hoare или C.A.R. Hoare) в 1960 году, вот только с ходу не смог найти, он в это время еще жил в Советском Союзе или уже вернулся в Великобританию.

Цитата дня


Есть два метода создания программного обеспечения. Один из них — сделать программу настолько простой, что, очевидно, в ней нет недостатков. И другой, сделать приложение настолько сложным, что в нем невидно явных недостатков.

 -- T. Hoare

P.s. Да, Quick Sort был разработан сэром Чарльзом Энтони Ричард Хоар (Charles Antony Richard Hoare или Tony Hoare или C.A.R. Hoare) в 1960 году, вот только с ходу не смог найти, он в это время еще жил в Советском Союзе или уже вернулся в Великобританию.

JS курсы: как расширить возможности разработчика сайтов

JS курсы: как расширить возможности разработчика сайтов

JavaScript курс JS пользуется спросом среди работников сферы информационных технологий. Без знаний этого языка программирования сложно себе представить работу востребованного на рынке IT-специалиста.

Зачем программистам знать JS?

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

Поскольку JavaScript — клиентский язык программирования (позволяет создать интерактивные элементы на сайте, каким его видят пользователи), он встроен в большинство известных браузеров. Это дает возможность размещать на интернет-страницах калькуляторы, всплывающие окна, движущиеся элементы и т.д.
Отсюда и востребованность специалистов, владеющих JS. Но, чтобы составить конкуренцию среди коллег и получать стоящие, интересные проекты по разработке сайтов с интеграцией JavaScript, нужно иметь основательные знания и практические наработки.
Основательный курс “JavaScript разработчик: продвинутые навыки разработки” предлагает Академия IMT в г. Днепр. Программа обучения составлена таким образом, чтобы за пять с половиной месяцев (42 занятия по 3 часа) даже новичок мог освоить новую профессию.

Для кого полезны JS курсы в IMT Академии?

  • Кто просто хочет больше знать о разработке веб-сайтов; кому интересны сайты и кто хочет их создавать. Состоявшиеся программисты изучают JS, чтобы внести возможности автоматизации на веб-страницах, делать сайты более привлекательными и продвинутыми с дизайнерской точки зрения; кто хочет получить практические навыки. Курс предусматривает достаточно домашних занятий, помогающих усвоить и закрепить пройденный материал. Преподаватели на протяжении обучения помогают разобраться с возникающими вопросами; кто хочет сделать перезагрузку в карьере. Из Академии IMT выпускаются специалисты, которые устраиваются на работу в известные компании, такие как “Shiftreset”, “Алло”, “МедСервис”, “Level Up” и другие.
  • Преподаватели курса — программисты-практики, специализирующиеся на C/C++, JAVA, PHP, JavaScript, Node.js, J2D/3D графике браузера, математическом моделировании интерфейса, разработке веб-приложений, RESTful-сервисов и гибридных мобильных приложений.


Курсы JS в Академии IMT является полный структурированный онлайн конспект с видео и заданиями для каждой лекции. Это первое учебное заведение, которое записывает все проведенные занятия. Запись можно просмотреть дома и восстановить упущенный материал.
В конце обучения студенты сдают тест или защищают выпускной проект. После успешной сдачи выпускники получают диплом с JavaScript-разработчика Академии IMT с уникальным номером, по которому можно проверить действительно ли программист окончил данный курс JavaScript.

Максимально ограничивайте область Generic-а и не используйте в перегрузках методов

Вчера исправлял баг, проявил он себя весьма интересно. Но продемонстрировать его можно на достаточно простом примере:

static void Main(string[] args)
{
    Print(new[] { 1, 2, 3 });
    Console.ReadKey();
}

static voidPrint<T>(T t)
{
    Console.WriteLine(t);
}

static voidPrint<T>(IEnumerable<T> t)
{
    foreach (var item in t)
    {
        Console.WriteLine(item);
    }
}
При запуске вместо ожидаемых 1, 2, 3 мы увидим:
Т.к. мы не задали ограничений на T, то и IEnumerable тоже приводится к T объявленному в первом методе. Накладывание ограничений на T позволило бы узнать о этой проблеме на этапе компиляции. Изменим код:
class Demo
{
    public int X { get; set; }
}

static void Main(string[] args)
{
    Print(new[] { new Demo { X = 1 }, new Demo { X = 2 }, new Demo { X = 3 } });
    Console.ReadKey();
}

static voidPrint<T>(T t) where T : Demo
{
    Console.WriteLine(t);
}

static voidPrint<T>(IEnumerable<T> t) where T : Demo
{
    foreach (var item in t)
    {
        Console.WriteLine(item);
    }

}
В данном примере я явно указал к чему должен приводиться T (к Demo или его потомкам). И вот вместо ошибки времени выполнения, мы получаем ошибку компиляции:
Error CS0311 The type 'ConsoleApp1.Program.Demo[]' cannot be used as type parameter 'T' in the generic type or method 'Program.Print(T)'. There is no implicit reference conversion from 'ConsoleApp1.Program.Demo[]' to 'ConsoleApp1.Program.Demo'.

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