Объявление и вызов методов в C#

Содержание

Слайд 2

Определение и вызов методов Знакомимся с созданием и вызовом методов, в

Определение и вызов методов

Знакомимся с созданием и вызовом методов, в

том числе перегруженных и принимающих переменное число параметров, а также инструметами рефакторинга, предоставленными Microsoft Visual Studio
Слайд 3

Что такое метод? Методы это имплементация поведения типа Метод содержит блок

Что такое метод?

Методы это имплементация поведения типа

Метод содержит блок кода, определяющий

действия, которые может выполнять тип

Весь код принадлежит методу

Методы позволяют инкапсулировать операции, которые защищают данные, хранимые внутри типа

Методы могут быть предназначены для внутреннего использования типа и быть закрытыми для других типов
Другие методы могут разрабатываться, чтобы позволить другим типам запрашивать выполнение определенного действия объекта, эти методы являются открытыми

Слайд 4

Что такое метод? C# поддерживает два типа методов Имя объекта Имя типа Имя метода Имя метода

Что такое метод?

C# поддерживает два типа методов

Имя объекта

Имя типа

Имя метода

Имя метода

Слайд 5

Создание метода Каждый метод в классе должен иметь уникальную сигнатуру

Создание метода

Каждый метод в классе должен иметь уникальную сигнатуру

Слайд 6

Создание метода

Создание метода

Слайд 7

Создание метода string MyMethod() { return "Hello"; }

Создание метода

string MyMethod()
{
return "Hello";
}

Слайд 8

Вызов метода Для вызова метода необходимо: указать имя метода предоставить в

Вызов метода

Для вызова метода необходимо:
указать имя метода
предоставить в скобках аргументы, соответствующие

параметрам метода
если метод возвращает значение, необходимо указать, как использовать это значение

public bool LockReport(string reportName, string userName)
{
bool success = false;
// Perform some processing here.
return success;
}

bool isReportLocked = LockReport("Medical Report", "Don Hall");

int Sum(int first, int second)
{
return first + second;
}

int i = 1;
int j = 2;
int result = Sum(i++, i+j);

result = 5

Аргументы метода вычисляются в строгом порядке слева-направо

Слайд 9

Создание и вызов перегруженных методов int intData = 99; bool booleanData

Создание и вызов перегруженных методов

int intData = 99;
bool booleanData = true;
//...
Console.WriteLine(intData);
Console.WriteLine(booleanData);


public void Deposit(decimal amount)
{
_balance += amount;
}
public void Deposit(string amount)
{
_balance += decimal.Parse(amount);
}
public void Deposit(int dollars, int cents)
{
_balance += dollars + (cents / 100.0m);
}

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

Слайд 10

Использование массива параметров Не всегда возможна перегрузка метода, принимающего переменное число

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

Не всегда возможна перегрузка метода, принимающего переменное число параметров,

особенно если не существует теоретических ограничений на их количество

int Add(int one, int two)
{
return one + two;
}

int Add(int one, int two, int three)
{
return one + two + three;
}

int Add(int one, int two, int three, int four)
{
return one + two + three + four;
}

int Add(. . .)
{
return one + two + three + four + . . .;
}

Слайд 11

Использование массива параметров int Add(int[] data) { int sum = 0;

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

int Add(int[] data)
{
int sum = 0;
for (int

i = 0; i < data.Length; i++)
{
sum += data[i];
}
return sum;
}

int[] myData = new int[4];
myData[0] = 99;
myData[1] = 2;
myData[2] = 55;
myData[3] = -26;
//...
int sum = myObject.Add(myData);

Необходимо вручную объявлять и заполнять массив данных

Слайд 12

Использование массива параметров int Add(params int[] data) { int sum =

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

int Add(params int[] data)
{
int sum = 0;
for

(int i = 0; i < data.Length; i++)
{
sum += data[i];
}
return sum;
}
...
int sum = myObject.Add(99, 2, 55, -26);

При определении метода с массивом параметров компилятор C# автоматически генерирует код, который создает массив из набора аргументов, указываемых при вызове метода

Ключевое слово params определяет массив параметров

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

Слайд 13

Рефакторинг для извлечения метода Рефакторинг – это процесс улучшения написанного ранее

Рефакторинг для извлечения метода

Рефакторинг – это процесс улучшения написанного ранее кода

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

Для осуществления рефакторинга существующего кода в метод необходимо выполнить следующие действия

В Visual Studio в окне редактора кода следует выбрать код, который необходимо реорганизовать в метод, щелкнуть правой кнопкой мыши пункт Refactor, а затем нажать кнопку Extract Method

В диалоговом окне Extract Method, в поле New method name нужно ввести имя метода, а затем нажать кнопку OK

1

2

Слайд 14

Рефакторинг для извлечения метода string messageContents = "My message text here";

Рефакторинг для извлечения метода

string messageContents = "My message text here";
string filePath

= @"C:\Users\Student\Desktop";
if (messageContents == null || messageContents == String.Empty)
{
throw new ArgumentException("Message cannot be empty");
}
if (filePath == null || !System.IO.File.Exists(filePath))
{
throw new ArgumentException("File path must exist");
}
File.AppendAllText(filePath, messageContents);
string messageContents = "My message text here";
string filePath = @"C:\Users\Student\Desktop";
LogMessage(messageContents, filePath);
File.AppendAllText(filePath, messageContents);
private static void LogMessage(string messageContents, string filePath)
{
if (messageContents == null || messageContents == String.Empty)
{
throw new ArgumentException("Message cannot be empty");
}
if (filePath == null || !System.IO.File.Exists(filePath))
{
throw new ArgumentException("File path must exist");
}
}
Слайд 15

Необязательные и выходные параметры Знакомимся с методами, принимающими необязательные параметры, а

Необязательные и выходные параметры

Знакомимся с методами, принимающими необязательные параметры, а

также с выходными параметрами и именованными аргументами
Слайд 16

Необязательные параметры Используются, когда не представляется возможным использовать перегрузку, поскольку типы

Необязательные параметры

Используются, когда не представляется возможным использовать перегрузку, поскольку типы параметров

не меняются так, чтобы компилятор проводил различие между реализациями

Используются при взаимодействии с другими технологиями, поддерживающими необязательные параметры
void MyMethod(int intData, float floatData, int moreIntData)
{
...
}
void MyMethod(int intData, float floatData)
{
...
}

int arg1 = 99;
float arg2 = 100.0F;
int arg3 = 101;
MyMethod(arg1, arg2, arg3);
MyMethod(arg1, arg2);

Слайд 17

Необязательные параметры void MyMethod(int intData) {...} void MyMethod(int moreIntData) {...} CTE

Необязательные параметры
void MyMethod(int intData)
{...}
void MyMethod(int moreIntData)
{...}

CTE

void MyMethod(int intData, float floatData,

int moreIntData = 99)
{
...
}
// Arguments provided for all three parameters
MyMethod(10, 123.45F, 99);
// Arguments provided for 1st two parameters only
MyMethod(100, 54.321F);
void MyMethod(int intData, float floatData = 101.1F, int moreIntData)
{...}
private static void Do(string massage, DateTime dt = DateTime.Now)
{...}

CTE

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

Нужно указать все обязательные параметры, прежде чем указывать любые необязательные

Слайд 18

Именованные аргументы Указав имена параметров можно обеспечить метод аргументами в последовательности,

Именованные аргументы

Указав имена параметров можно обеспечить метод аргументами в последовательности, которая

отличается от порядка параметров в его сигнатуре

void MyMethod(int first, double second, string third)
{. . .}
. . .
MyMethod(third: "Hello", first: 1234, second: 12.12);

При использовании именованных аргументов в сочетании с необязательными параметрами, можно пропускать параметры

Объявление метода

Вызов метода с именованными аргументами

Можно смешивать позиционированные и именованные аргументы

Следует указывать все позиционированные аргументы до именованных

Слайд 19

Выходные параметры Позволяют получить из метода дополнительные данные Для определения выходного

Выходные параметры

Позволяют получить из метода дополнительные данные

Для определения выходного параметра, следует

добавить ключевое слово out к параметру метода
void MyMethod(int first, double second, out int data)
{
...
data = 99;
}

int value;
MyMethod(10, 101.1F, out value);

int value;
MyMethod(10, 101.1F, value);

Присваивать начальное значения не обязательно

Обязательно присвоить соответствующие значения

value = 99

CTE

Слайд 20

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Знакомимся

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

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения
void

M1()
{
string name = "Joe";
M2(name);
. . .
return;
}

. . .

Стек потока перед вызовом метода M1

Стек потока

Слайд 22

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения
void

M1()
{
string name = "Joe";
M2(name);
. . .
return;
}

. . .

Размещение локальной переменной name метода M1 в стеке потока

name(string)

string name = "Joe";

Стек потока

{

Слайд 23

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения
void

M1()
{
string name = "Joe";
M2(name);
. . .
return;
}

. . .

Размещение аргументов метода М2 и адреса возврата в стек потока

name(string)
void M2(string s)
{
int length = s.Length;
int tally;
. . .
return;
}

s(string)

[return adress]

M2(name);

Стек потока

void M2(string s)

Слайд 24

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения
void

M1()
{
string name = "Joe";
M2(name);
. . .
return;
}

. . .

name(string)
void M2(string s)
{
int length = s.Length;
int tally;
. . .
return;
}

s(string)

length(int)

tally(int)

Стек потока

Выделение в стеке потока памяти для локальных переменных метода М2

int length = s.Length;

[return adress]

int tally;

{

return;

}

Слайд 25

void M1() { string name = "Joe"; M2(name); . . .

void M1()
{
string name = "Joe";
M2(name);
. . .
return;
}

.

. .

Стековый фрейм М2 возвращается в первоначальное состояние

name(string)

M2(name);

Стек потока

return;

}

Стековый фрейм М1 возвращается в первоначальное состояние, M1 возвращает управление вызывающей функции, устанавливая указатель команд процессора на адрес возврата

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Слайд 26

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

internal

class Employee
{
public int GetYearsEmployed { ... }
public virtual string GetProgressReport { ... }
public static Employee Lookup(string name) { ... }
}
internal sealed class Manager : Employee
{
public override string GetProgressReport { ... }
}
Слайд 27

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения
void

M3()
{
Employee e;
int year;
e = new Manager();
e = Employee.Lookup("Joe");
year = e.GetYearsEmployeed();
e.GetProgressReport();
}

Управляемая куча

Стек потока

CLR загружена в процесс, его куча инициализирована, готовится вызов стека потока, в который загружен метод МЗ

Слайд 28

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения
void

M3()
{
Employee e;
int year;
e = new Manager();
e = Employee.Lookup("Joe");
year = e.GetYearsEmployeed();
e.GetProgressReport();
}

Управляемая куча

Стек потока

Type object ptr
Sync block index
Static fields
GetProgressReport

Manager Type Object
Type object ptr
Sync block index
Static fields
GetYearsEmployed
GetProgressReport
Lookup

Employee Type Object

При вызове метода МЗ создаются объекты типа Employee и Manager

Слайд 29

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения
void

M3()
{
Employee e;
int year;
e = new Manager();
e = Employee.Lookup("Joe");
year = e.GetYearsEmployeed();
e.GetProgressReport();
}

Управляемая куча

Стек потока

Type object ptr
Sync block index
Static fields
GetProgressReport

Manager Type Object
Type object ptr
Sync block index
Static fields
GetYearsEmployed
GetProgressReport
Lookup

Employee Type Object

Employee e;

int year;

e(Employee)

year(int)

null

0

Выделение памяти в стеке потока для локальных переменных метода МЗ

Слайд 30

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения
void

M3()
{
Employee e;
int year;
e = new Manager();
e = Employee.Lookup("Joe");
year = e.GetYearsEmployeed();
e.GetProgressReport();
}

Управляемая куча

Стек потока

e(Employee)

year(int)

Type object ptr
Sync block index
Instance fields

Type object ptr
Sync block index
Static fields
GetProgressReport

Manager Object

Manager Type Object
Type object ptr
Sync block index
Static fields
GetYearsEmployed
GetProgressReport
Lookup

Employee Type Object

e = new Manager();

0

Создание и инициализация объекта Manager

Слайд 31

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения
void

M3()
{
Employee e;
int year;
e = new Manager();
e = Employee.Lookup("Joe");
year = e.GetYearsEmployeed();
e.GetProgressReport();
}

Управляемая куча

Стек потока

e(Employee)

year(int)

Type object ptr
Sync block index
Instance fields

Type object ptr
Sync block index
Static fields
GetProgressReport

Manager Object

Manager Type Object

Type object ptr
Sync block index
Instance fields

Manager Object
Type object ptr
Sync block index
Static fields
GetYearsEmployed
GetProgressReport
Lookup

Employee Type Object

JITted
code

e = Employee.Lookup("Joe");

0

Статический метод Lookup в Employee выделяет память и инициализирует объект Manager значением Joe

Слайд 32

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения
void

M3()
{
Employee e;
int year;
e = new Manager();
e = Employee.Lookup("Joe");
year = e.GetYearsEmployeed();
e.GetProgressReport();
}

Управляемая куча

Стек потока

e(Employee)

year(int)

Type object ptr
Sync block index
Instance fields

Type object ptr
Sync block index
Static fields
GetProgressReport

Manager Object

Manager Type Object

Type object ptr
Sync block index
Instance fields

Manager Object
Type object ptr
Sync block index
Static fields
GetYearsEmployed
GetProgressReport
Lookup

Employee Type Object

JITted
code

JITted
code

year = e.GetYearsEmployeed();

Невиртуальный экземплярный метод GetYearsEmployeed в Employee возвращает значение 5

5

Слайд 33

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения
void

M3()
{
Employee e;
int year;
e = new Manager();
e = Employee.Lookup("Joe");
year = e.GetYearsEmployeed();
e.GetProgressReport();
}

Управляемая куча

Стек потока

e(Employee)

year(int)

Type object ptr
Sync block index
Instance fields

Type object ptr
Sync block index
Static fields
GetProgressReport

Manager Object

Manager Type Object

Type object ptr
Sync block index
Instance fields

Manager Object
Type object ptr
Sync block index
Static fields
GetYearsEmployed
GetProgressReport
Lookup

Employee Type Object

JITted
code

JITted
code

JITted
code

e.GetProgressReport();

При вызове виртуального метода GetProgressReport экземпляра Employee будет вызвана переопределенная реализация этого метода в Manager

5

Слайд 34

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения

Взаимодействие типов, объектов, стека потока и управляемой кучи во время выполнения
void

M3()
{
Employee e;
int year;
e = new Manager();
e = Employee.Lookup("Joe");
year = e.GetYearsEmployeed();
e.GetProgressReport();
}

Управляемая куча

Стек потока

e(Employee)

year(int)

Type object ptr
Sync block index
Instance fields

Type object ptr
Sync block index
Static fields
GetProgressReport

Manager Object

Manager Type Object

Type object ptr
Sync block index
Instance fields

Manager Object
Type object ptr
Sync block index
Static fields
GetYearsEmployed
GetProgressReport
Lookup

Employee Type Object
Type object ptr
Sync block index
Static fields
. . .

Type Type Object

JITted
code

JITted
code

JITted
code

Объекты типа Manager и Employee как экземпляры типа System.Type

5