C# — краткое знакомство

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

Но сначала небольшое отступление насчет .Net. Полагаю, все, кто пишет под него, и немалая часть остальных разработчиков в курсе, но я это все же напишу — для себя и для тех, кому дотнет в новинку. Основа мощи и гибкости платформы в том, что она состоит как бы из двух уровней. Нижний уровень — реализация платформы для конкретной системы. Сюда же входят все классы, библиотеки и фреймворки. Верхний уровень — языки и среды программирования. Да, это напоминает джаву. Но есть и отличия. В дотнете, как и в джаве, исходный код компилируется в байт-код (IL — Immediate Language). Но структура этого кода не привязана к какой-либо процессорной архитектуре. Это дает возможность проще и быстрее, а главное, без глюков и потерь, компилировать код IL непосредственно в код для конкретного процессора, на котором он выполняется, прямо на лету (JIT компиляция).

Подключение «модулей» платформы, фреймворка или вашей программы

Весь код пишется внутри какого-либо пространства имен, а типы доступны, например, как MyApp.MyType1

Вывод на консоль

Чтение строки с консоли (до ввода Enter)

Объявление класса с точкой входа в программу

Типы данных

1. Типы значений (не-ссылочные)

2. Ссылочные типы

Объявление переменных

Создание объектов

Константы. Константы всегда неявно статические!

Операции со строками

Перечисления (только целочисленные!); трактуется как int

Модификаторы полей:

      public — всем
      protected — себе и потомкам
      internal — себе и коду в сборке
      protected internal — себе, потомкам и коду в сборке
      private — только себе

По умолчанию поля считаются private.
У интерфейсов все члены трактуются public, но модификаторы явно не ставятся.

Перечисления из битовых флагов:

При выводе на консоль печататься будет не число, а список флагов (если в значении более одного бита установлено).

Перечисления по умолчанию соответствуют int, но это легко изменить:

Оператор is — проверка на соответствие типу (точнее, является ли А наследником Б).
Оператор as — возвращает либо ссылку на А но уже типа Б, либо null, если преобразование невозможно. Исключение не возбуждается.

Если в методе необходимо изменять значение передаваемого аргумента, его надо задавать как ref _type_ _name_:

Константные поля всегда неявно статичны (принадлежат классу, а не объекту). Другой вариант задания «констант» — поля static readonly. Их значение можно задавать сколько угодно раз, но только в пределах конструктора (в данном случае, статического).

Свойства:

Если не указать set, то будет свойство только для чтения.

Автореализуемые свойства:

Если надо ридонли:

Задавать значение такому свойству можно только в конструкторе.

При перекрытие метода в потомке надо добавлять слово new:

Пока это все. Позже, может быть, еще добавлю. 🙂

11 комментариев

  1. Да, это напоминает джаву. Но есть и отличия. В дотнете, как и в джаве, исходный код компилируется в байт-код (IL — Immediate Language). Но структура этого кода не привязана к какой-либо процессорной архитектуре.

    А разве в Java байт-код привязан к процессорной архитектуре? Я точно видел как Java-проект скомпилированный на 32-х разрядной машине спокойно работал в Линухе на Итаниуме.

    using norsys = System;

    Мне привычнее слева видеть настоящее имя импортируемого пакета (модуля и т.п.), а уже справа — его алиас. Так сделано, например, в Scala.

    Перечисления (только целочисленные!); трактуется как int

    В Java это вполне себе класс, который может и методы свои иметь и имплементить интерфейсы и экстендить классы. Чего с ним только не делают.

    Оператор as — возвращает либо ссылку на А но уже типа Б, либо null, если преобразование невозможно. Исключение не возбуждается.

    Странная особенность. Мне кажется что умалчивать о несоответствии типов это как-то не правильно.

    Автореализуемые свойства

    Удобный синтаксический сахар 🙂

    При перекрытие метода в потомке надо добавлять слово new

    Странный синтаксический перец 🙂

    1. А если скомпилировать под 64 бита, на 32 битах запустится?

      Здесь (в шарпе) насчет классовости перечислений не уверен, потому не прокомментирую.

      О несоответствии типов не умалчивается. Если тип можно привести к желаемому — будет валидный указатель, если нет — null. Исключение в таком раскладе не требуется. Кроме того, as, в отличие от is, используется именно для приведения, а не для проверки на «родство», что и делает вариант без возбуждения исключений более предпочтительным. Опять же, исключение часто обрабатывается вне блока, где вы используете as и процесс обработки списка (если вы по списку идете) будет прерван. Это легко обойти, сделав еще один блок отлова на нужном уровне, но код от этого читабельнее точно не станет.

      Удобный синтаксический сахар? Возможно. Но в чем смысл постоянно писать кучу кода? Ах, ну да, есть же отличные ИДЕ с генераторами кода. Только вот сам код распухает и становится менее читабельным от множества лишних строк. Вместо 60% полезной информации на один экран влезает уже всего 30-40%. Так что «сахар» не только удобен, но и полезен.

      Насчет new ниже описано точнее. Первый вариант был добавлен в заметку как странная особенность, но позже по ходу чтения выяснилось, что это не так чтобы обязательно именно new, там еще override есть. 🙂

      В целом же заметка писалась как кратенькая памятка основ шарпа. Шарп в чем-то лучше других, в чем-то хуже. Потому что у него своя ниша. Как и у других распространенных языков. Многие, например, ругают Objective-C за его синтаксис. А меня он прикалывает — вполне удобно и просто. Особенно в последних версиях, где уже вовсе не нужно заботиться о памяти, если вы используете только ARC. Да и в целом синтаксис вполне прозрачный у эплов. Правда и у них косяки бывают. 🙂

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

        Есть проблема, но о ней не сообщается — это и есть замалчивание. А вообще очень логично выглядит, ага:

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

        В Java для проверки на родство тоже есть отдельная конструкция: instanceof. Приведение типа используется для приведения типа, а не для проверки на «родство».

        Опять же, исключение часто обрабатывается вне блока, где вы используете as и процесс обработки списка (если вы по списку идете) будет прерван. Это легко обойти, сделав еще один блок отлова на нужном уровне, но код от этого читабельнее точно не станет.

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

        1. Валер, as не совсем для приведения используется. Приведение типа выглядит так же как и в джаве. Обычное. А as используется в случаях когда ты уверен, что тип в переменной родственный. Замалчивания не происходит, т.к., повторюсь, исключение в этом случае не требуется. Определить, что тип не соответствует все еще можно по нуллу.

          1. То есть в C# две конструкции приведения типа? И в случае не совпадения типа одна из них бросает исключение, а другая возвращает null? Тогда в этом есть смысл, но по тексту статьи я решил что конструкция только одна.

      2. А если скомпилировать под 64 бита, на 32 битах запустится?

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

          1. Получается, что я не понял тонкостей, в чем именно отличие. 🙂

  2. «Они преглянулись и он понял, что он понял, что он не понял…»
    Или что тоже похоже: «Я оглянулся посмотерть, не оглянулась ли она, чтоб посмотреть не оглянулся ли я….»;D

Leave a Reply

Ваш e-mail не будет опубликован. Обязательные поля помечены *