Public и static в определении метода Main()
Скачать 28.55 Kb.
|
У каждого приложения на С# должен быть метод Main, определенный в одном из его классов. Кроме того, этот метод должен быть определен как public и static (ниже я объясню, что значит static). Для компилятора С# ле важно, в каком из классов определен метод Main, а класс, выбранный для этого, не влияет на порядок компиляции. Здесь есть отличие от C++, так как там зависимости должны тщательно отслеживаться при сборке приложения. Компилятор С# достаточно "умен", чтобы самостоятельно просмотреть ваши файлы исходного кода и отыскать метод Main. Между тем этот очень важный метод является точкой входа во все приложения на С#.
Все члены класса - поля, методы, свойства - все они имеют модификаторы доступа. Модификаторы доступа позволяют задать допустимую область видимости для членов класса. То есть контекст, в котором можно употреблять данную переменную или метод. В предыдущей теме мы уже с ними сталкивались, когда объявляли поля класса Book публичными (то есть с модификатором public). В C# применяются следующие модификаторы доступа:
Объявление полей класса без модификатора доступа равнозначно их объявлению с модификатором private. Классы, объявленные без модификатора, по умолчанию имеют доступ internal.
Открытый интерфейс по умолчанию для класса – это набор открытых членов данного класса. это набор тех переменных, свойств и методов-членов, к которым можно обратиться в формате имя_объекта.член_класса (с точки зрения обращения к членам класса). это набор тех членов класса, которые объявлены с использованием ключевого слова public (с точки зрения определения класса). В C# открытый интерфейс по умолчанию для класса может состоять из следующих членов этого класса:
Еще одной разновидностью члена класса является свойство. Как правило, свойство сочетает в себе поле с методами доступа к нему. Как было показано в приведенных ранее примерах программ, поле зачастую создается, чтобы стать доступным для пользователей объекта, но при этом желательно сохранить управление над операциями, разрешенными для этого поля, например, ограничить диапазон значений, присваиваемых данному полю. Этой цели можно, конечно, добиться и с помощью закрытой переменной, а также методов доступа к ее значению, но свойство предоставляет более совершенный и рациональный путь для достижения той же самой цели. Свойства очень похожи на индексаторы. В частности, свойство состоит из имени и аксессоров getи set. Аксессоры служат для получения и установки значения переменной. Главное преимущество свойства заключается в том, что его имя может быть использовано в выражениях и операторах присваивания аналогично имени обычной переменной, но в действительности при обращении к свойству по имени автоматически вызываются его аксессоры get и set. Аналогичным образом используются аксессоры get и set индексатора.
Перейдем к работе с методами в производных классах. Понятно, что методы объявленные с модификатором public или protected можно использовать в производном классе без проблем. Представляет интерес возможность замещения методов в производном классе. Тут есть две возможности: • полное замещение метода базового класса без поддержки полиморфизма; • перегрузка метода базового класса с поддержкой полиморфизма.
В большинстве случаев вам нужно переопределять методы, а не скрывать их. Скрывая методы, вы рискуете вызывать "неверный" метод для экземпляра данного класса. Однако, как показано в следующем примере,синтаксис С# спроектирован так, чтобы гарантировать, что разработчик будет предупрежден об этой потенциальной проблеме при компиляции, тем самым обеспечивая возможность более безопасного сокрытия методов, если это действительно нужно. Это также дает преимущества разработчикам библиотек классов при работе с разными версиями. Предположим, имеется класс HisBaseClass: class HisBaseClass { // разнообразные члены } В какой-то момент в будущем вы напишете класс-наследник, добавляющий некоторую функциональность к HisBaseClass. В частности, добавите метод MyGroovyMethod (), которого нет в базовом классе: class MyDerivedCJass: HisBaseClass { public int MyCruovyMethod() { // некая превосходная реализация return 0; } }
Первый закон приведения типов звучит так: если один класс является производным от другого, всегда безопасно ссылаться на объект производного класса через объект базового класса. В результате мы можем использовать в C# весьма мощные программные конструкции. Например, если у нас определен метод для увольнения сотрудника: public class TheMachine I public static void FlreTlrisPerson(Employee e) // Удаляем сотрудника из базы данных // Отбираем у него ключ и точилку для карандашей }
Базовый класс System.Enum является абстрактным, поэтому не может напрямую иметь экземпляры (объекты), а может использоваться только как базовый в цепочке наследования. Тем не менее он определяет ряд статических методов, позволяющих обрабатывать созданные перечисления. Вот некоторые из этих методов.
Безуcловно, задачу поиска и замены подстроки в строке можно решить на C# с использованием различных методов System.String иSystem.Text.StringBuilder. Однако в некоторых случаях это потребует написания большого объема кода C#. Если вы используете регулярные выражения, то весь этот код сокращается буквально до нескольких строк. По сути, вы создаете экземпляр объекта RegEx, передаете ему строку для обработки, а также само регулярное выражение (строку, включающую инструкции на языке регулярных выражений) — и все готово. В следующей таблице показана часть информации о перечислении RegexOptions, экземпляр которого можно передать конструктору класса RegEx
Вызывать две функции-члена, чтобы получить два значения, не всегда удобно, поэтому было бы хорошо иметь возможность получить оба значения с помощью только одного вызова функции. Однако функция может возвращать только одно значение. Решение этой проблемы заключается в том, чтобы использовать ссылочный (или ref) параметр. При этом значения параметров, передаваемых функции, могут быть изменены: // error using System; class Point { public Point(int x, int y) { this.x = x; this.y = y; } // get both values in one function call public void GetPoint(ref int x, ref int y) { x = this.x; y = this.y; } int x; int y; } class Test { public static void Main() { Point myPoint = new Point(10, 15); int x; int y; // illegal myPoint.GetPoint(ref x, ref y); Console.WriteLine("myPoint({0}, {1})", x, y); } }
При объявлении переменной мы можем воспользоваться ключевым словом var, в этом случае сам компилятор определяет тип:
Также присутствует особый тип dynamic. Суть его в том, что компилятор будет пропускать проверки типов при компиляции и осуществлять их только при выполнении операции. struct Point { int x; } Point p = new Point(); dynamic pNew = p; pNew.x = 3; pNew.y = "Red";
|