Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Перегрузка операторов в С#  (Прочитано 10450 раз)
0 Пользователей и 1 Гость смотрят эту тему.
xelos
Гость
« : 22-08-2004 13:26 » 

Доброго всем...

1.в общем у меня не проблема даже, а просто вопрос, разъяснений хочется.
Переписываю один проект с C++ на С#. Работаю со своими классами пусть class Test. в С++ в классе была перегрузка оператора равно (operator=).
поискал я в хелпе на С#, оператор равно в C# не перегружается. в общем, сделал отдельный метод для копирования объекта T.Copy(). Запустил программу - все работает. и тут гляжу, что в одном месте забыл я поменять оператор = на оператор копирования. однако все работает! вопрос: в С# оператор = перегружается автоматически??? (было у меня подозрение, что так оно и есть, если определен конструктор по копии, однако убрав конструктор по копии все равно все работает).

P.S. в классе есть несколько членов - типа целочисленные. Именно они-то и копируются автоматом.

2.  шаблонов, как я понимаю, в C# нет... есть класс реализующий подобие динамических массивов. переписывать его для каждого типа данных долго и некрасиво. как быть?
Записан
xelos
Гость
« Ответ #1 : 22-08-2004 13:46 » 

еще такой вопрос про указатели. в С++ есть:
Код:
        int *vect;
         vect=new int[size];
//когда надо удалить, делаем
if (vect!=NULL)
delete [] vect;
vect=NULL;

если я в С# сдклаю просто vect=null это будет иметь тот же эффект? и надо ли вообще это делать?
« Последнее редактирование: 30-11-2007 22:49 от Алексей1153++ » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 23-08-2004 06:36 » 

1. про "=": пока не скажу (до работы надо добраться), но где-то там есть чёткое разграничение, что копируется, а что ссылается. А ещё есть ключевое слово ref, означающее ссылку - в параметрах я его точно видел, а вот в коде... - опять ж, посмотреть надо Улыбаюсь.
2. Про NULL: в общем случае делать не надо, есть собрщик мусора.
3. Про шаблоны: в .NET Framework 2.0 обещали - ждём-с Улыбаюсь.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Alex White
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #3 : 23-08-2004 09:44 » 

Все объекты наследованые от ValueType при присвоении копируются, остальные все ссылаются.

Про null - если хочется убить объект класса - смело присваивай ему null. Но как верно замечено в предыдущем посте, на это можно забить, и в конце работы приложения GC все приберет сам.

Кстати есть классы, которые реализуют некое подобие динамических массивов. Я сам когда переписывал код с + на # , столкнулся с похожей проблемой. Эти классы лежат в намспейсе System.Collections. Я написал динамический массив с произвольным доступом на основе System.Collections.ArrayList и System.Collections.IEnumerator.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 23-08-2004 11:08 » 

Из книжки "C# для профессионалов" т.1, стр. 46
Цитата
... в отличие от более старых языков, где разработчик должен был указывать объекты, для которых требовалось использовать кучу, в C# этот выбор осуществляется компилятором в зависимости от типа данных объекта.

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

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

и ниже

Цитата
В C# основные типы данных, такие как bool и long, являются типами по значению.

Цитата
Большинство сложных типов данных C#, включая классы, определяемые пользователем, являются типами по ссылке.

Цитата
... необходимо помнить, что тип struct является в C# типом по значению.

на стр. 157 в подразделе "Переменные по ссылке и по значению: что происходит в памяти" читаем:

Цитата
Необходимо помнить, что большая часть предлагаемого материала не документирована. Эта глава должна рассматриваться как упрощённое руководство, а не точное описание реализации схемы управления памятью.
т.е. в истинность нижеследующего никто не гарантирует - в лучших традициях Microsoft  Отлично

для переменных по значению всё стандартно
Цитата
Невозможно написать фрагмент кода на C#, в котором переменная B объявлена после A, но A выходит из области видимости первой.
т.е. стек
Цитата
Отметим, что если компилятор встречает строку типа int I, J, то порядок вхождения в область видимости выглядит неопределённым.
далее
Цитата
Нередко важно использовать некий метод для выделения памяти под некоторые данные и иметь доступ к ним ещё долго после выхода из метода. Такая возможность предоставляется, если память для хранения запрашивается с помощью оператора new - как в случае всех типов по ссылке.

Цитата
Типы по ссылке включают в себя все классы, а также массивы. Например, строка:

Код:
int [] X = {3, 4, 5, 6, 7};

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

Код:
int [] X = new int [5] {3, 4, 5, 6, 7};
ну и для строк, соответственно, также.

Т.е. твоё копирование на деле есть лишь ссылка, а объект физически продолжает существовать один. Проверяй внимательно.

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

У класса есть 3 стандартных деструктора: Close(), Dispose() и Finalize(). Где Close() - логический деструктор (логически завершает работу с объектом, но не удаляет его, т.е. объект можно продолжать использовать), Dispose() - полный ручной деструктор (после его выполнения объект удаляется, т.е. его нельзя больше использовать, но память не очищается), Finalize() - полный автоматический деструктор (его вызывает сборщик мусора, для ручного вызова он недоступен). Внутри Dispose следует вызвать System.GC.SuppressFinalize(), чтобы сборщик мусора не выполнял Finalize, когда будет перерабатывать кучу и физически удалять удалённый через Dispose объект.
« Последнее редактирование: 30-11-2007 22:51 от Алексей1153++ » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
xelos
Гость
« Ответ #5 : 23-08-2004 12:10 » 

в общем, лучше использовать оператор типа T.Copy(TClass T1); если я правильно понимаю...

объявления:
TClass T = new TClass(); //создается ссылка и объект в памяти
TClass T1 = new TClass(); //вторая ссылка и второй объект в памяти
T1.Copy(T); // должно работать?

потому что если Т1=Т; //второй указатель указывает на то же самое, что и первый... однако, что же происходит с памятью для второго объекта? она больше недоступна и второй объект автоматом уничтожается? Сорри, просто не совсем понятно как управление памятью в .NET происходит.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 23-08-2004 12:59 » 

именно так! если ссылок на второй объект больше нет (не переменных, по которым его можно выудить), объект будет удалён сборщиком мусора.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
xelos
Гость
« Ответ #7 : 23-08-2004 13:03 » 

спасибо, понятно... поосторожней буду с копированием объектов...
Записан
xelos
Гость
« Ответ #8 : 23-08-2004 17:29 » 

с оператором = разобрался, действительно, присваивается указатель, а не создается копия объекта. теперь копирование реализую через вспомогательный метод Copy(ClassT T). однако выскакивает ошибка при выполнении кода:
Код:
public void AddTache(CTache T)
{

CTache[] TacheTemp;
int i;
TacheTemp=new CTache[size+1];

T.Index=size;
TacheTemp[size].Copie(T); //ОШИБКА ЗДЕСЬ!
size=size+1;

}
выдает: Object reference not set to an instance of an object.
я так понял, что нет указателя на объект. В массиве ссылки хранятся? Функция копирования:
Код:
public void Copie(CTache T)
{
Index=T.Index;
Competence=T.Competence;
DueDate=T.DueDate;
Duree=T.Duree;
DureeOpt=T.DureeOpt;
Site=T.Site;
}
получается, что оператор массива TacheTemp[size] - возвращает объект, а надо чтобы указатель возвращался?
в функции Copie(CTache T) и AddTache(CTache T) передается указатель?

что сбивает с толку, что код
Код:
CTache T = new CTache();
//инициализация T
CTache R = new CTache();
R.Copie(T);
работает без проблем и так как надо (в памяти два разных объекта)...
« Последнее редактирование: 30-11-2007 22:53 от Алексей1153++ » Записан
xelos
Гость
« Ответ #9 : 23-08-2004 17:43 » 

кажется разобрался, но не уверен. чтобы все работало, строчку где ошибка, заменяю на:
TacheTemp[size] = new CTache(T); //ОШИБКИ БОЛЬШЕ НЕТ
получается, что когда первый раз создаем массив - это мы резервируем место под массив указателей:
Код:
        CTache[] TacheTemp;
         TacheTemp=new CTache[size+1];//массив указателей
теперь, когда заполняем массив, надо зарезервировать место под объекты?
Код:
//для каждого указателя создаем объект в памяти?
TacheTemp[size] = new CTache(T);
может кто-нибудь прокомментирует?
« Последнее редактирование: 30-11-2007 22:54 от Алексей1153++ » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 23-08-2004 19:32 » 

Именно так, получается массив указателей. См. выше: переменные классы хранят указатели. Поэтому для при заполнении массива каждый элемент надо создать через new, либо хранить ссылки на один и тот же объект в разных элементах массива.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines