Example: Passing Reference Types by Reference 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Example: Passing Reference Types by Reference



This example is the same as the previous example, except for using the ref keyword in the method header and call. Any changes that take place in the method will affect the original variables in the calling program.

class PassingRefByRef { static void Change(ref int[] pArray) { // Both of the following changes will affect the original variables: pArray[0] = 888; pArray = new int[5] {-3, -1, -2, -3, -4}; System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]); }   static void Main() { int[] arr = {1, 4, 5}; System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr[0]);   Change(ref arr); System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr[0]); } }

Output

Inside Main, before calling the method, the first element is: 1

Inside the method, the first element is: -3

Inside Main, after calling the method, the first element is: -3

Code Discussion

All of the changes that take place inside the method affect the original array in Main. In fact, the original array is reallocated using the new operator. Thus, after calling the Change method, any reference to arr points to the five-element array, which is created in the Change method.


Пример. Передача ссылочных типов по ссылке

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

ß------

 

Результат

Inside Main, before calling the method, the first element is: 1

Inside the method, the first element is: -3

Inside Main, after calling the method, the first element is: -3

Рассмотрение кода

Все изменения, выполняемые внутри метода, влияют на исходный массив в Main. В действительности исходный массив перераспределяется с помощью оператора new. Поэтому после вызова метода Change любая ссылка на arr указывает на массив из пяти элементов, созданный в методе Change.

 


Example: Swapping Two Strings

Swapping strings is a good example of passing reference-type parameters by reference. In the example, two strings, str1 and str2, are initialized in Main and passed to the SwapStrings method as parameters modified by the ref keyword. The two strings are swapped inside the method and inside Main as well.

class SwappingStrings { static void SwapStrings(ref string s1, ref string s2) // The string parameter is passed by reference. // Any changes on parameters will affect the original variables. { string temp = s1; s1 = s2; s2 = temp; System.Console.WriteLine("Inside the method: {0} {1}", s1, s2); }   static void Main() { string str1 = "John"; string str2 = "Smith"; System.Console.WriteLine("Inside Main, before swapping: {0} {1}", str1, str2);   SwapStrings(ref str1, ref str2); // Passing strings by reference System.Console.WriteLine("Inside Main, after swapping: {0} {1}", str1, str2); } }

Output

Inside Main, before swapping: John Smith

Inside the method: Smith John

Inside Main, after swapping: Smith John

Code Discussion

In this example, the parameters need to be passed by reference to affect the variables in the calling program. If you remove the ref keyword from both the method header and the method call, no changes will take place in the calling program.


Пример. Перестановка двух строк

Перестановка строк представляет собой хороший пример передачи параметров ссылочного типа по ссылке. В данном примере две строки str1 и str2 инициализируются в Main и передаются в метод SwapStrings в качестве параметров, изменяемых по ключевому слову ref. Эти две строки переставляются внутри метода и также внутри Main.

ß----

 

 

Результат

Inside Main, before swapping: John Smith

Inside the method: Smith John

Inside Main, after swapping: Smith John

Рассмотрение кода

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

Дополнительные сведения о строках см. в разделе Строка.

 


Constructors

Whenever a class or struct is created, its constructor is called. A class or struct may have multiple constructors that take different arguments. Constructors enable the programmer to set default values, limit instantiation, and write code that is flexible and easy to read.

If you do not provide a constructor for your object, C# will create one by default that instantiates the object and sets member variables to the default values. Static classes and structs can also have constructors.

Using Constructors

Constructors are class methods that are executed when an object of a given type is created. Constructors have the same name as the class, and usually initialize the data members of the new object.

In the following example, a class named Taxi is defined by using a simple constructor. This class is then instantiated with the new operator. The Taxi constructor is invoked by the new operator immediately after memory is allocated for the new object.

public class Taxi { public bool isInitialized; public Taxi() { isInitialized = true; } }   class TestTaxi { static void Main() { Taxi t = new Taxi(); System.Console.WriteLine(t.isInitialized); } }

A constructor that takes no parameters is called a default constructor. Default constructors are invoked whenever an object is instantiated by using the new operator and no arguments are provided to new.


Конструкторы

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

Если не предоставить конструктор для объекта, C# создаст конструктор по умолчанию, который создаст экземпляр объекта и задаст переменным-членам значения по умолчанию. Статические классы и структуры также могут иметь конструкторы.

Использование конструкторов

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

В следующем примере класс Taxi определяется с помощью простого конструктора. После этого с помощью оператора new создается экземпляр класса. Конструктор Taxi вызывается оператором new сразу после выделения памяти для нового объекта.

ß-----

 

 

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

 


Unless the class is static, classes without constructors are given a public default constructor by the C# compiler in order to enable class instantiation.

You can prevent a class from being instantiated by making the constructor private, as follows:

class NLog { // Private Constructor: private NLog() { }   public static double e = System.Math.E; //2.71828... }

Constructors for struct types resemble class constructors, but structs cannot contain an explicit default constructor because one is provided automatically by the compiler. This constructor initializes each field in the struct to the default values. However, this default constructor is only invoked if the struct is instantiated with new. For example, this code uses the default constructor for Int32, so that you are assured that the integer is initialized:

int i = new int(); Console.WriteLine(i);

The following code, however, causes Compiler Error CS0165 because it does not use new, and because it tries to use an object that has not been initialized:

int i; Console.WriteLine(i);

Alternatively, objects based on structs can be initialized or assigned and then used as in the following example:

int a = 44; // Initialize the value type... int b; b = 33; // Or assign it before using it. Console.WriteLine("{0}, {1}", a, b);

So calling the default constructor for a value type is not required.

 


Компилятор C# предоставляет классам без конструкторов открытый конструктор по умолчанию, чтобы обеспечить создание экземпляров класса, если класс не является статическим. Дополнительные сведения см. в разделе Статические классы и члены статических классов.

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

ß-----

Дополнительные сведения см. в разделе Закрытые конструкторы.

Конструкторы для типов структур похожи на конструкторы классов, но structs не могут содержать явно указанный конструктор по умолчанию, поскольку такой конструктор автоматически предоставляется компилятором. Этот конструктор инициализирует все поля в struct их значениями по умолчанию. Однако конструктор по умолчанию вызывается только в том случае, если создается экземпляр struct при помощи оператора new. Например, следующий код использует конструктор по умолчанию для Int32 таким образом, чтобы гарантировать инициализацию целочисленного значения.

int i = new int(); Console.WriteLine(i);

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

int i; Console.WriteLine(i);

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

int a = 44; // Initialize the value type... int b; b = 33; // Or assign it before using it. Console.WriteLine("{0}, {1}", a, b);

Поэтому вызов конструктора по умолчанию для типа значения не требуется.

 


Both classes and structs can define constructors that take parameters. Constructors that take parameters must be called through a new statement or a base statement. Classes and structs can also define multiple constructors, and neither is required to define a default constructor. For example:

public class Employee { public int salary;   public Employee(int annualSalary) { salary = annualSalary; }   public Employee(int weeklySalary, int numberOfWeeks) { salary = weeklySalary * numberOfWeeks; } }

This class can be created by using either of the following statements:

Employee e1 = new Employee(30000); Employee e2 = new Employee(500, 52);

A constructor can use the base keyword to call the constructor of a base class. For example:

public class Manager: Employee { public Manager(int annualSalary) : base(annualSalary) { //Add further instructions here. } }

 


Классы и structs могут определять конструкторы, использующие параметры. Конструкторы, использующие параметры, нужно вызывать с помощью операторов new или base. Классы и structs также могут определять несколько конструкторов; они не требуются для определения конструктора по умолчанию. Пример.

ß------

 

Этот класс можно создать с помощью любого из следующих операторов:

Employee e1 = new Employee(30000); Employee e2 = new Employee(500, 52);

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

public class Manager: Employee { public Manager(int annualSalary) : base(annualSalary) { //Add further instructions here. } }

 


In this example, the constructor for the base class is called before the block for the constructor is executed. The base keyword can be used with or without parameters. Any parameters to the constructor can be used as parameters to base, or as part of an expression.

In a derived class, if a base-class constructor is not called explicitly by using the base keyword, the default constructor, if there is one, is called implicitly. This means that the following constructor declarations are effectively the same:

public Manager(int initialdata) { //Add further instructions here. }
public Manager(int initialdata): base() { //Add further instructions here. }

If a base class does not offer a default constructor, the derived class must make an explicit call to a base constructor by using base.

A constructor can invoke another constructor in the same object by using the this keyword. Like base, this can be used with or without parameters, and any parameters in the constructor are available as parameters to this, or as part of an expression. For example, the second constructor in the previous example can be rewritten using this:

public Employee(int weeklySalary, int numberOfWeeks) : this(weeklySalary * numberOfWeeks) { }

The use of the this keyword in the previous example causes this constructor to be called:

public Employee(int annualSalary) { salary = annualSalary; }

Constructors can be marked as public, private, protected, internal, or protectedinternal. These access modifiers define how users of the class can construct the class. For more information, see Access Modifiers.

A constructor can be declared static by using the static keyword. Static constructors are called automatically, immediately before any static fields are accessed, and are generally used to initialize static class members. For more information, see Static Constructors.

 


В этом примере конструктор базового класса вызывается перед выполнением блока конструктора. Ключевое слово base можно использовать как с параметрами, так и без них. Любые параметры конструктора можно указывать для оператора base или в составе выражения.

Если конструктор базового класса не вызывается явным образом в производном классе при помощи ключевого слова base, то вызывается конструктор по умолчанию, если он существует. Это означает, что следующие объявления конструкторов действуют одинаково:

ß----

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

Конструктор может вызывать в том же самом объекте другой конструктор с помощью ключевого слова this. Как и base, ключевое слово this можно использовать с параметрами или без параметрами, а все параметры конструктора доступны в качестве параметров this или в составе выражения. Например, второй конструктор в предыдущем примере можно переписать с помощью this:

ß----

Использование ключевого слова this в предыдущем примере приводит к вызову этого конструктора:

ß-------

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

Конструктор можно объявить статическим при помощи ключевого слова static. Статические конструкторы вызываются автоматически непосредственно перед доступом к статическим полям и обычно служат для инициализации членов статического класса. Дополнительные сведения см. в разделе Статические конструкторы.

 


Instance Constructors

Instance constructors are used to create and initialize instances. The class constructor is invoked when you create a new object, for example:

class CoOrds { public int x, y;   // constructor public CoOrds() { x = 0; y = 0; } }
Note:
For clarity, this class contains public data members. This is not a recommended programming practice because it allows any method anywhere in a program unrestricted and unverified access to an object's inner workings. Data members should generally be private, and should be accessed only through class methods and properties.

This constructor is called whenever an object based on the CoOrds class is created. A constructor like this one, which takes no arguments, is called a default constructor. However, it is often useful to provide additional constructors. For example, we can add a constructor to the CoOrds class that allows us to specify the initial values for the data members:

// A constructor with two arguments: public CoOrds(int x, int y) { this.x = x; this.y = y; }

This allows CoOrd objects to be created with default or specific initial values, like this:

CoOrds p1 = new CoOrds(); CoOrds p2 = new CoOrds(5, 3);

Конструкторы экземпляров

Конструкторы экземпляров используется для создания и инициализации экземпляров. Конструктор класса вызывается при создании нового объекта, например:

ß------

 

Примечание.
Следует пояснить, что этот класс содержит открытые члены данных. Такой подход не рекомендуется использовать на практике, поскольку в этом случае любой метод в любом месте программы получает неограниченный и неконтролируемый доступ к внутренней работе объекта. Члены данных обычно должны быть закрытыми, а доступ к ним должен осуществляться только посредством методов и свойства класса.

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

ß-----

 

 

Это позволяет создавать объекты CoOrd с начальными значениями по умолчанию или с другими начальными значениями:

CoOrds p1 = new CoOrds(); CoOrds p2 = new CoOrds(5, 3);

 


If a class does not have a default constructor, one is automatically generated and default values are used to initialize the object fields, for example, an int is initialized to 0. Therefore, because the CoOrds class default constructor initializes all data members to zero, it can be removed altogether without changing how the class works. A complete example using multiple constructors is provided in Example 1 later in this topic, and an example of an automatically generated constructor is provided in Example 2.

Instance constructors can also be used to call the instance constructors of base classes. The class constructor can invoke the constructor of the base class through the initializer, as follows:

class Circle: Shape { public Circle(double radius) : base(radius, 0) { } }

In this example, the Circle class passes values representing radius and height to the constructor provided by Shape from which Circle is derived. A complete example using Shape and Circle appears in this topic as Example 3.

 


Если у класса нет конструктора по умолчанию, такой конструктор создается автоматически, а для инициализации полей объектов используются значения по умолчанию, int инициализируется со значением 0. Следовательно, поскольку конструктор по умолчанию класса CoOrds инициализирует все члены данных с нулевыми значениями, его можно удалить, при этом порядок работы класса не изменится. Полный пример использования нескольких конструкторов см. в данном разделе в примере 1; пример автоматически созданного конструктора см. в примере 2.

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

class Circle: Shape { public Circle(double radius) : base(radius, 0) { } }

В этом примере класс Circle передает значения радиуса и высоты конструктору, предоставленному классом Shape, для которого класс Circle является производным. Полный текст кода с использованием классов Shape и Circle см. в данном разделе в примере 3.

 


Example 1

The following example demonstrates a class with two class constructors, one without arguments and one with two arguments.

class CoOrds { public int x, y;   // Default constructor: public CoOrds() { x = 0; y = 0; }   // A constructor with two arguments: public CoOrds(int x, int y) { this.x = x; this.y = y; }   // Override the ToString method: public override string ToString() { return (System.String.Format("({0},{1})", x, y)); } }   class MainClass { static void Main() { CoOrds p1 = new CoOrds(); CoOrds p2 = new CoOrds(5, 3);   // Display the results using the overriden ToString method: System.Console.WriteLine("CoOrds #1 at {0}", p1); System.Console.WriteLine("CoOrds #2 at {0}", p2); } }

Output

CoOrds #1 at (0,0)

CoOrds #2 at (5,3)


Пример 1

В следующем примере демонстрируется класс с двумя конструкторами, один из которых не имеет аргументов, а второй имеет два аргумента.

ß------

 

Результат

CoOrds #1 at (0,0)

CoOrds #2 at (5,3)

 


Example 2

In this example, the class Person does not have any constructors, in which case, a default constructor is automatically provided and the fields are initialized to their default values.

public class Person { public int age; public string name; }   class TestPerson { static void Main() { Person p = new Person();   System.Console.Write("Name: {0}, Age: {1}", p.name, p.age); } }

Output

Name:, Age: 0

Notice that the default value of age is 0 and the default value of name is null.

Example 3

The following example demonstrates using the base class initializer. The Circle class is derived from the general class Shape, and the Cylinder class is derived from the Circle class. The constructor on each derived class is using its base class initializer.


Пример 2

В этом примере класс Person не имеет конструкторов, поэтому автоматически предоставляется конструктор по умолчанию, а все поля инициализируются со значениями по умолчанию.

public class Person { public int age; public string name; }   class TestPerson { static void Main() { Person p = new Person();   System.Console.Write("Name: {0}, Age: {1}", p.name, p.age); } }

Результат

Name:, Age: 0

Обратите внимание, что в значение по умолчанию age равно 0, а значение по умолчанию name равно null.

Пример 3

В следующем примере кода демонстрируется использование инициализатора базового класса. Класс Circle является производным от основного класса Shape, а класс Cylinder является производным от класса Circle. Конструктор каждого производного класса использует инициализатор своего базового класса.

 


 

abstract class Shape { public const double pi = System.Math.PI; protected double x, y; public Shape(double x, double y) { this.x = x; this.y = y; } public abstract double Area(); } class Circle: Shape { public Circle(double radius) : base(radius, 0) { } public override double Area() { return pi * x * x; } } class Cylinder: Circle { public Cylinder(double radius, double height) : base(radius) { y = height; } public override double Area() { return (2 * base.Area()) + (2 * pi * x * y); } } class TestShapes { static void Main() { double radius = 2.5; double height = 3.0; Circle ring = new Circle(radius); Cylinder tube = new Cylinder(radius, height); System.Console.WriteLine("Area of the circle = {0:F2}", ring.Area()); System.Console.WriteLine("Area of the cylinder = {0:F2}", tube.Area()); } }

Output:

Area of the circle = 19.63 Area of the cylinder = 86.39


 

 

ß-----------

 

Результат

Area of the circle = 19.63

Area of the cylinder = 86.39

 


Private Constructors

A private constructor is a special instance constructor. It is generally used in classes that contain static members only. If a class has one or more private constructors and no public constructors, other classes (except nested classes) cannot create instances of this class. For example:

class NLog { // Private Constructor: private NLog() { }   public static double e = System.Math.E; //2.71828... }

The declaration of the empty constructor prevents the automatic generation of a default constructor. Note that if you do not use an access modifier with the constructor it will still be private by default. However, the private modifier is usually used explicitly to make it clear that the class cannot be instantiated.

Private constructors are used to prevent creating instances of a class when there are no instance fields or methods, such as the Math class, or when a method is called to obtain an instance of a class. If all the methods in the class are static, consider making the complete class static.

 


Закрытые конструкторы

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

class NLog { // Private Constructor: private NLog() { }   public static double e = System.Math.E; //2.71828... }

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

Закрытые конструкторы используются, чтобы не допустить создание экземпляров класса при отсутствии полей или методов экземпляра, например для класса Math, или когда осуществляется вызов метода для получения экземпляра класса. Если все методы в классе являются статическими, имеет смысл сделать статическим весь класс. Дополнительные сведения см. в разделе Статические классы и члены статических классов.

 


Example

The following is an example of a class using a private constructor.

public class Counter { private Counter() { } public static int currentCount; public static int IncrementCount() { return ++currentCount; } }   class TestCounter { static void Main() { // If you uncomment the following statement, it will generate // an error because the constructor is inaccessible: // Counter aCounter = new Counter(); // Error   Counter.currentCount = 100; Counter.IncrementCount(); System.Console.WriteLine("New count: {0}", Counter.currentCount); } }

Output

New count: 101

Notice that if you uncomment the following statement from the example, it will generate an error because the constructor is inaccessible because of its protection level:

// Counter aCounter = new Counter(); // Error

 


Пример

Ниже приведен пример класса с закрытым конструктором.

ß-------

 

Результат

New count: 101

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

// Counter aCounter = new Counter(); // Error

 


Static Constructors

A static constructor is used to initialize any static data, or to perform a particular action that needs performed once only. It is called automatically before the first instance is created or any static members are referenced.

class SimpleClass { // Static constructor static SimpleClass() { //... } }

Static constructors have the following properties:

· A static constructor does not take access modifiers or have parameters.

· A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced.

· A static constructor cannot be called directly.

· The user has no control on when the static constructor is executed in the program.

· A typical use of static constructors is when the class is using a log file and the constructor is used to write entries to this file.

· Static constructors are also useful when creating wrapper classes for unmanaged code, when the constructor can call the LoadLibrary method.

 


Статические конструкторы

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

class SimpleClass { // Static constructor static SimpleClass() { //... } }

Статические конструкторы обладают следующими свойствами.

· Статический конструктор не принимает модификаторы доступа и не имеет параметров.

· Статический конструктор вызывается автоматически для инициализации класса перед созданием первого экземпляра или ссылкой на какие-либо статические члены.

· Статический конструктор нельзя вызывать напрямую.

· Пользователь не управляет тем, когда статический конструктор выполняется в программе.

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

· Статические конструкторы также полезны при создании классов-оболочек для неуправляемого кода, когда конструктор может вызвать метод LoadLibrary.

 


Example

In this example, the class Bus has a static constructor and one static member, Drive(). When Drive() is called, the static constructor is invoked to initialize the class.

public class Bus { // Static constructor: static Bus() { System.Console.WriteLine("The static constructor invoked."); }   public static void Drive() { System.Console.WriteLine("The Drive method invoked."); } }   class TestBus { static void Main() { Bus.Drive(); } }

Output

The static constructor invoked.

The Drive method invoked.

 


Пример

В следующем примере класс Bus имеет статический конструктор и один статический член, Drive(). При вызове члена Drive() статический конструктор вызывается для инициализации класса.

public class Bus { // Static constructor: static Bus() { System.Console.WriteLine("The static constructor invoked."); }   public static void Drive() { System.Console.WriteLine("The Drive method invoked."); } }   class TestBus { static void Main() { Bus.Drive(); } }

Результат

The static constructor invoked.

The Drive method invoked.

 



Поделиться:


Последнее изменение этой страницы: 2017-01-19; просмотров: 94; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.117.183.172 (0.135 с.)