Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
GEK / ООП_ГОСЫ_ОТВЕТЫ.docx
Скачиваний:
68
Добавлен:
18.05.2015
Размер:
1.83 Mб
Скачать

Конфликты областей видимости полей и локальных переменных

В некоторых случаях два идентификатора с одинаковыми именами (хотя и не совпадающими полностью уточненными именами) и одинаковой областью видимости можно различить, и тогда компилятор допускает объявление второй переменной. Причина в том, что С# делает принципиальное различие между переменными, объявленными на уровне типа (полями) и переменными, объявленными в методах (локальными). Рассмотрим следующий фрагмент кода:

using System;

namespace ConsoleApplication1

{

class Program

{

static int j = 20;

public static void Main()

{

int j = 30;

Console.WriteLine(j);

return;

}

}

Этот код компилируется, несмотря на то, что здесь в контексте метода Main() присутствуют две переменных с именем j: переменная j, определенная на уровне класса и существующая до тех пор, пока не будет уничтожен класс (когда завершится метод Main(), а вместе с ним и программа), и переменная j, определенная внутри Main(). В данном случае новая переменная с именем j, объявленная в методе Main(), скрывает переменную уровня класса с тем же именем. Поэтому когда вы запустите этот код, на дисплее будет отображено число 30.

Константы

Как следует из названия, константа — это переменная, значение которой не меняется за время ее существования. Предваряя переменную ключевым словом const при ее объявлении и инициализации, вы объявляете ее как константу:

const int a = 100; // Это значение не может быть изменено

Ниже перечислены основные характеристики констант:

  • Они должны инициализироваться при объявлении, и однажды присвоенные им значения никогда не могут быть изменены.

  • Значение константы должно быть вычислено во время компиляции. Таким образом, инициализировать константу значением, взятым из другой переменной, нельзя. Если все-таки нужно это сделать, используйте поля только для чтения.

  • Константы всегда неявно статические. Однако вы не должны (и фактически не можете) включать модификатор static в объявление константы.

Использование констант в программах обеспечивает, по крайней мере, три преимущества:

  • Константы облегчают чтение программ, заменяя "магические" числа и строки читаемыми именами, назначение которых легко понять.

  • Константы облегчают модификацию программ. Например, предположим, что в программе С# имеется константа SalesTax (налог с продаж), которой присвоено значение 6 процентов. Если налог с продаж когда-нибудь изменится, вы можете модифицировать все вычисления налога, просто присвоив новое значение этой константе, и не понадобится просматривать код в поисках значений О.О6 изменять каждое из них, надеясь, что оно нигде не будет пропущено.

  • Константы позволяют избежать ошибок в программах. Если попытаться присвоить новое значение константе где-то в другом месте программы, а не там, где она объявлена, компилятор выдаст сообщение об ошибке.

Модификаторы доступа

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

public

Ключевое слово public является модификатором доступа для типов и членов типов. Общий (public) доступ является уровнем доступа с максимальными правами. Ограничений доступа к общим членам не существует, как показано в следующем примере:

Копировать

class SampleClass

{

public int x; // No access restrictions.

}

Дополнительные сведения см. в разделах Модификаторы доступа (Руководство по программированию в C#) и Уровни доступности (Справочник по C#).

Пример

В следующем примере объявляются два класса: PointTest и MainClass. Доступ к общим членам x и y класса PointTest осуществляется непосредственно из класса MainClass.

C#

Копировать

class PointTest

{

public int x;

public int y;

}

class MainClass4

{

static void Main()

{

PointTest p = new PointTest();

// Direct access to public members:

p.x = 10;

p.y = 15;

Console.WriteLine("x = {0}, y = {1}", p.x, p.y);

}

}

// Output: x = 10, y = 15

Если уровень доступа public изменить на private или protected, то в результате будет выводиться следующее сообщение об ошибке:

Доступ к элементу "PointTest.y" невозможен из-за его уровня защиты.

protected

Ключевое слово protected является модификатором доступа к члену. Доступ к члену с модификатором protected возможен внутри класса и из производных экземпляров класса. Для сравнения ключевого слова protected с другими модификаторами доступа см. раздел Уровни доступности.

Пример

Член базового класса с модификатором protected доступен в производном классе только в том случае, если доступ осуществляется через тип производного класса. В качестве примера рассмотрим следующий фрагмент кода:

C#

Копировать

class A

{

protected int x = 123;

}

class B : A

{

static void Main()

{

A a = new A();

B b = new B();

// Error CS1540, because x can only be accessed by

// classes derived from A.

// a.x = 10;

// OK, because this class derives from A.

b.x = 10;

}

}

Оператор a.x = 10 генерирует ошибку, поскольку он произведен внутри статического метода Main, а не внутри экземпляра класса B.

Элементы структур не могут использоваться с модификатором protected, потому что наследование от структуры невозможно.

В этом примере класс DerivedPoint является производным от класса Point. Следовательно, доступ к членам базового класса с модификатором protected можно осуществлять непосредственно из производного класса.

C#

Копировать

class Point

{

protected int x;

protected int y;

}

class DerivedPoint: Point

{

static void Main()

{

DerivedPoint dpoint = new DerivedPoint();

// Direct access to protected members:

dpoint.x = 10;

dpoint.y = 15;

Console.WriteLine("x = {0}, y = {1}", dpoint.x, dpoint.y);

}

}

// Output: x = 10, y = 15

Если изменить уровень доступа к переменным x и y на private, то компилятор выдаст следующие сообщения об ошибке:

'Point.y' is inaccessible due to its protection level.

'Point.x' is inaccessible due to its protection level.

internal

Ключевое слово internalмодификатор доступа для типов и членов типов. Внутренние типы или члены доступны только внутри файлов в одной и той же сборке (см. следующий пример).

Копировать

public class BaseClass

{

// Only accessible within the same assembly

internal static int x = 0;

}

Доступ к типам или членам с модификатором доступа protected internal может осуществляться из текущей сборки или из типов, которые являются производными от содержащего их класса.

Сравнение модификатора internal с другими модификаторами доступа см. в разделах Уровни доступности (Справочник по C#) и Модификаторы доступа (Руководство по программированию в C#).

Дополнительные сведения о сборках см. в разделе Сборки и глобальный кэш сборок (C# и Visual Basic).

Внутренний доступ чаще всего используется в разработке на основе компонентов, так как он позволяет группе компонентов взаимодействовать в закрытой форме, не открывая доступ остальной части кода приложения. Например, структура для построения графических пользовательских интерфейсов может предоставлять классы Control и Form, взаимодействующие при помощи членов с внутренним доступом. Так как эти члены являются закрытыми, они не предоставляются коду, использующему структуру.

Создание ссылки на тип или член с внутренним доступом за пределами сборки, в которой он был определен, приведет к ошибке.

Пример

В этом примере содержится два файла: Assembly1.cs и Assembly1_a.cs. Первый файл содержит внутренний базовый класс BaseClass. Попытка создания экземпляра BaseClass во втором файле приведет к ошибке.

Копировать

// Assembly1.cs

// Compile with: /target:library

internal class BaseClass

{

public static int intM = 0;

}

Копировать

// Assembly1_a.cs

// Compile with: /reference:Assembly1.dll

class TestAccess

{

static void Main()

{

BaseClass myBase = new BaseClass(); // CS0122

}

}

В этом примере используются те же файлы, что и в примере 1, но уровень доступности BaseClass изменен на public. Кроме того, уровень доступности члена IntM изменен на internal. В этом случае можно создать экземпляр класса, но доступ к внутреннему члену отсутствует.

Копировать

// Assembly2.cs

// Compile with: /target:library

public class BaseClass

{

internal static int intM = 0;

}

Копировать

// Assembly2_a.cs

// Compile with: /reference:Assembly1.dll

public class TestAccess

{

static void Main()

{

BaseClass myBase = new BaseClass(); // Ok.

BaseClass.intM = 444; // CS0117

}

}

private

Ключевое слово private является модификатором доступа к члену. Закрытый (private) доступ является уровнем доступа с минимальными правами. Доступ к закрытым членам можно получить только внутри тела класса или структуры, в которой они объявлены, как показано в следующем примере:

Копировать

class Employee

{

private int i;

double d; // private access by default

}

Вложенные типы в том же теле могут также обращаться к таким закрытым членам.

Ошибка времени компиляции возникнет в том случае, если создать ссылку на закрытый член за пределами класса или структуры, в которой он объявлен.

Сравнение модификатора private с другими модификаторами доступа см. в разделах Уровни доступности (Справочник по C#) и Модификаторы доступа (Руководство по программированию в C#).

Пример

В этом примере класс Employee содержит два закрытых элемента данных – name и salary. Как к закрытым членам, к ним нельзя получить доступ кроме как через методы членов. Для получения управляемого доступа к закрытым членам можно использовать методы с именем GetName и Salary. Доступ к методу name можно получить через открытый метод, а к методу salary – через открытое свойство только для чтения. (Дополнительные сведения см. в разделе Свойства (Руководство по программированию в C#).)

C#

Копировать

class Employee2

{

private string name = "FirstName, LastName";

private double salary = 100.0;

public string GetName()

{

return name;

}

public double Salary

{

get { return salary; }

}

}

class PrivateTest

{

static void Main()

{

Employee2 e = new Employee2();

// The data members are inaccessible (private), so

// they can't be accessed like this:

// string n = e.name;

// double s = e.salary;

// 'name' is indirectly accessed via method:

string n = e.GetName();

// 'salary' is indirectly accessed via property

double s = e.Salary;

}

}

При помощи модификаторов доступа можно задать следующие пять уровней доступности:

public : Неограниченный доступ.

protected : Доступ ограничен содержащим классом или типами, которые являются производными от содержащего класса.

Internal : Доступ ограничен текущей сборкой.

protected internal: Доступ ограничен пределами сборки или типа, который является производным от данного класса.

private : Доступ ограничен содержащим типом.

Соседние файлы в папке GEK