Здравствуйте, Qbit86, Вы писали:
QВ> C# аналогом плюсового деструктора является метод Dispose() (а не финализатор, как думают некоторые),
Не соглашусь. В C#, как языке, нет прямого аналога деструкторам из C++. Их признаки распилены между финализаторами и реализацией соглашений по IDisposable.
Как и деструкторы в C++, финализаторы вызываются runtime'ом вне нормального контекста исполнения кода, и ограничены в том что могут безопасно делать "унутре". Dispose() выступает второй половиной — детерминированный вызов, в конкретном месте, в конкретное время.
Однако если посмотреть на дело с точки зрения логической организации работы с ресурсами, то именно финализатор аналог деструктора. Бо решает ту же проблему: забыли освободить ресурс нормальным образом.
Здравствуйте, MxKazan, Вы писали:
MK>Здравствуйте, -MyXa-, Вы писали:
D>>>Ну какой же это метод ??? Это обычный указатель на член класса (pointer to member), со всеми своими дежурными тараканами. MX>>Интересно послушать про тараканов. MK>Не переводи тему. Попался ведь
MX>>И, если знаете, про то, почему не-типы нельзя в generic-и по-чём зря совать. MK>Я не фига не понял эту фразу. Какие не типы по-чем совать generic зря? Что там нельзя в generic засунуть?
Своим "Попался ведь" попались Вы, MxKazan. Вы мало того, что не знаете, что такое template non-type parameter (как тут правильно подсказывают). Вы не понимаете, что нет контекста, в котором было бы важно — указатель там или не указатель. И, судя по тому, что Вы повелись на слова "pointer to member" (где на самом деле должно быть "pointer to member function"), поторопившись сказать "Не переводи тему", Вы просто не понимаете, что это одна тема, т.к. в данном случае "член класса" = метод. Велика беда указатель на метод! Очевидно, что мой код, в котором вызывается переданный метод, Вы не осилили тоже. Я так понимаю, Вы просто из группы поддержки — руками-ногами помахать, вклиниться в чужой разговор.
Если не поможет, будем действовать током... 600 Вольт (C)
Здравствуйте, Sinclair, Вы писали:
S>>>Поэтому соглашение об инкременте указателя придется выполнять самостоятельно. Q>>Поясни. S>Очень просто. Вот у нас есть S>
S>public static void EpicFail(HugeBitmap bmp)
S>{
S> RefCounter<HugeBitmap> c;
S> using(var a = new RefCounter<HugeBitmap>(bmp)); // bmp.refCount++;
S> {
S> var b = new RefCounter(a); // bmp.refCount++
S> c = a; // oops... вот в этот момент С++ инкрементирует указатель. С# - нет.
S> b.Dispose(); //bmp.refCount--
S> } // bmp.refCount-- => bmp.Release()
S> c.Reference.Draw(); // InvalidOperationException!
S>}
S>
S>Вся дупа в том, что нет в дотнете перегрузки оператора присваивания. А конструктором копирования обязательно нужно не забыть попользоваться. Непонятно даже, насколько это плохо по сравнению с плюсами, в которых можно забыть воспользоваться shared_ptr.
А причём тут RefCounter, а? Эдак можно по отношению к любому disposable типу сказать, что им опасно пользоваться, потому что «c = a;». Подставь вместо RefCounter StreamReader, и увидишь ту же проблему, когда через одну ссылку ты уже закрыл поток, а через другую пытаешься из него считать.
S>
S>c = a; // oops... вот в этот момент С++ инкрементирует указатель. С# - нет.
Это не имеет абсолютно никакого отношения к оператору присваивания. Это имеет отношение лишь к пониманию человеком семантики косвенности. Я тебе такой же пример могу и на C++ слабать:
Человек либо понимает «семантику указателей», либо нет. «Помнить о том, что её надо не забыть» — ну ведь бред же! Потенциальная возможность запутаться в «c = a;» может быть спровоцирована, например, предшествующим C++-background'ом. То есть это не свойство языка, а скорее свойство программиста. Опытный дотнетчик со временем перестаёт воспринимать значок «=» в контексте плюсовой «перегрузки оператора присваивания».
S>Вся дупа в том, что нет в дотнете перегрузки оператора присваивания.
А я утверждаю, что есть. Называется Assign(), или Clone(), или Copy(), как удобно. Правда, не «перегрузка», и не «оператора», but who cares?
S>А конструктором копирования обязательно нужно не забыть попользоваться.
Вот не понимаю я этой фразы. Как так, не забыть? Типа, нужно мне отсортировать массив функцией Quicksort, но я её забыл, поэтому переставил в нём элементы функцией Reverse, так что ли? Либо мне нужна семантика обычного копирования ссылок, тогда я использую значок «=». Либо мне нужна какая-то другая логика, тогда я вызываю предусмотренную для того функцию.
S>>>Поэтому соглашение об инкременте указателя придется выполнять самостоятельно.
В .NET ты должен «помнить» (хотя при чём тут помнить, должен знать семантику операторов языка, если называешь себя .NET-программистом), что в нашей задаче так нельзя:
c = a;
а нужно так:
c.Assign(a);
В C†† ты должен «помнить» (опять же, лучше не помнить, а понимать), что вот так нельзя:
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>>>Как раз таки — тип. D>>Неправда.
ГВ>Я имел в виду именно тип самого члена класса.
А зачем Вы его имели в виду ? Он ведь и там, и сям есть.
ГВ>>>Where is a difference? D>>Вам неясна разница между указателем и тем на что он указывает ???
ГВ>В терминах C++ метод нельзя передать как параметр иначе, чем в виде указателя.
Это личные проблемы C++. Разница между указателем и тем на что он указывает от этого не исчезает. D>>Круто. И эти люди пишут на C++
ГВ>О! В том, что я не понимаю, что такое указатель, меня ещё никто не обвинял.
Вы что-то путаете. Свои заблуждения Вы демонстрируете сами. Я тут совершенно непричём
Здравствуйте, drol, Вы писали:
D>Как и деструкторы в C++, финализаторы вызываются runtime'ом вне нормального контекста исполнения кода, и ограничены в том что могут безопасно делать "унутре". Dispose() выступает второй половиной — детерминированный вызов, в конкретном месте, в конкретное время.
D>Однако если посмотреть на дело с точки зрения логической организации работы с ресурсами, то именно финализатор аналог деструктора. Бо решает ту же проблему: забыли освободить ресурс нормальным образом.
Финализатор в этом случае скорее всего даже не вызовется, если конкретная реализация стримридера грамотно реализует Dispose (с вызовом GC.SupressFinalize).
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>Вариантов может быть много.
Это всё, конечно, очень интересно, но только причём здесь свойства-то ?
Ну наваяли Вы какую-то инфраструктуру, и что ? Частью языка она ведь от этого не стала. Обычные классы. На .NET/C# всё можно сделать аналогично, но только чуть лучше Бо есть свойства, и можно связать их с полученным framework'ом. Более того, такие вещи уже давно входят в комплект — в WPF и WF есть могучая конструкция DependencyProperty, например.
Здравствуйте, -MyXa-, Вы писали:
MX>Своим "Попался ведь" попались Вы, MxKazan. Вы мало того, что не знаете, что такое template non-type parameter (как тут правильно подсказывают). Вы не понимаете, что нет контекста, в котором было бы важно — указатель там или не указатель. И, судя по тому, что Вы повелись на слова "pointer to member" (где на самом деле должно быть "pointer to member function"), поторопившись сказать "Не переводи тему", Вы просто не понимаете, что это одна тема, т.к. в данном случае "член класса" = метод. Велика беда указатель на метод! Очевидно, что мой код, в котором вызывается переданный метод, Вы не осилили тоже. Я так понимаю, Вы просто из группы поддержки — руками-ногами помахать, вклиниться в чужой разговор.
Ну что я могу сказать. Если я действительно неправильно понял код, то виноват, да.
Здравствуйте, drol, Вы писали:
ГВ>>>>Как раз таки — тип. D>>>Неправда. ГВ>>Я имел в виду именно тип самого члена класса. D>А зачем Вы его имели в виду ? Он ведь и там, и сям есть.
Ну, давай поделим. Тип значения свойства и тип объекта, представляющего собой свойство. Я говорю о типе объекта, представляющего собой свойство.
ГВ>>>>Where is a difference? D>>>Вам неясна разница между указателем и тем на что он указывает ??? ГВ>>В терминах C++ метод нельзя передать как параметр иначе, чем в виде указателя. D>Это личные проблемы C++. Разница между указателем и тем на что он указывает от этого не исчезает.
Очень смешно. И что?
Кстати, можешь предложить не-хакерский способ оперирования телом функции "по значению"?
D>>>Круто. И эти люди пишут на C++ ГВ>>О! В том, что я не понимаю, что такое указатель, меня ещё никто не обвинял. D>Вы что-то путаете. Свои заблуждения Вы демонстрируете сами. Я тут совершенно непричём
А... Не забудь сказать, что я сел в лужу, проявил истинное ламерство и самое главное — не меньше трёх раз призвать меня признать своё поражение. Только это всё не в одном постинге, конечно, а так, в разбивку. В одном сообщении про лужу, в другом про ламерство. Одним словом, я в тебя верю.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>Здравствуйте, drol, Вы писали:
ГВ>>>>>Как раз таки — тип. D>>>>Неправда. ГВ>>>Я имел в виду именно тип самого члена класса. D>>А зачем Вы его имели в виду ? Он ведь и там, и сям есть.
ГВ>Ну, давай поделим. Тип значения свойства и тип объекта, представляющего собой свойство. Я говорю о типе объекта, представляющего собой свойство.
Блин. Я не въезжаю. Что это за тип такой, "представляющий свойство"? Т.е. ты берешь и объявляешь какой-то свой тип и говоришь, мол, оно есть свойство? Тогда можно в пример привести DependencyProperty
Здравствуйте, Qbit86, Вы писали:
S>>А конструктором копирования обязательно нужно не забыть попользоваться.
Q>Вот не понимаю я этой фразы. Как так, не забыть?
Предположу, что имеется в виду, например, передача RefCounter<HugeBitmap> в качестве параметра метода:
void foo(RefCounter<HugeBitmap> hugeBitmap);
тогда вызывать её надо так:
using (RefCounter<HugeBitmap> hugeBitmap = new RefCounter<HugeBitmap>(new HugeBitmap()))
{
foo(hugeBitmap.Clone()); // правильно
//foo(hugeBitmap); // ошибка
}
Если не поможет, будем действовать током... 600 Вольт (C)
Здравствуйте, drol, Вы писали:
ГВ>>Вариантов может быть много. D>Это всё, конечно, очень интересно, но только причём здесь свойства-то ?
Меня спросили — я ответил.
D>Ну наваяли Вы какую-то инфраструктуру, и что ? Частью языка она ведь от этого не стала. Обычные классы. На .NET/C# всё можно сделать аналогично, но только чуть лучше Бо есть свойства, и можно связать их с полученным framework'ом. Более того, такие вещи уже давно входят в комплект — в WPF и WF есть могучая конструкция DependencyProperty, например.
DependencyProperty — это тоже самый обычный класс. Пример его привязки к классу-носителю показан прямо в MSDN:
public class MyStateControl : ButtonBase
{
public MyStateControl() : base() { }
public Boolean State
{
get { return (Boolean)this.GetValue(StateProperty); }
set { this.SetValue(StateProperty, value); }
}public static readonly DependencyProperty StateProperty = DependencyProperty.Register(
"State", typeof(Boolean), typeof(MyStateControl),new PropertyMetadata(false));
}
Dependency properties and the WPF property system extend property functionality by providing a type that backs a property, as an alternative implementation to the standard pattern of backing the property with a private field. The name of this type is DependencyProperty. The other important type that defines the WPF property system is DependencyObject. DependencyObject defines the base class that can register and own a dependency property.
Following is a summation of the terminology that is used in this software development kit (SDK) documentation when discussing dependency properties:
*Dependency property: A property that is backed by a DependencyProperty.
*Dependency property identifier: A DependencyProperty instance, which is obtained as a return value when registering a dependency property, and then stored as a member of a class. This identifier is used as a parameter in many of the APIs that interact with the WPF property system. *CLR "wrapper": The actual get and set implementations for the property. These implementations incorporate the dependency property identifier by using it in the GetValue and SetValue calls, thus providing the backing for the property using the WPF property system.
Вот мы сейчас говорим на самом деле о том самом "set/get implementation". Хотя по сути мой пример со "сложным свойством" отдалённо перекликается с идеей DependencyProperty.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Q>В C†† ты должен «помнить» (опять же, лучше не помнить, а понимать), что вот так нельзя: Q>
std::tr1::shared_ptr<int const> const q(p.get());
Q>а нужно так: Q>
std::tr1::shared_ptr<int const> const q(p);
Q>33 отличия?
Вообще-то в С++ в shared_ptr свет клином-то не упёрся. Бывают, например, интрузивные владеющие COW указаетли.
Мало того, в С++ я могу заиметь класс, в котором одно из полей будет таким умным указателем, при этом пользователи этого класса ничего про это знать не обязаны. А в ХиндиСи придётся и пользователю объемлющего классу от использования значка = воздерживаться и т. д...
Короче, IMHO? лучше в ХиндиСи парадигму COW не использовать... Ясно же, раз Хинди, значит на COW замахиваться нельзя!!!
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Я совсем про другое веду речь. Перечитайте мой предыдущий постинг ещё пару-тройку раз
*Намекаю — не о "неявности" разговор
using — это как раз тот самый "нормальный образ". От того что вызов Dispose() "вывалян в синтаксическом сахаре", он не перестаёт быть обычным вызовом метода в нормальном контексте исполнения кода. Деструкторы и финализаторы же вызываются совсем другим макаром.
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>DependencyProperty — это тоже самый обычный класс.
Про то и базар. Так вот ещё раз повторяю вопрос: причём тут свойства-то ? Они ведь как были, так и остались конструкцией языка, независимо от потрохов set/get. И все их полезные фичи никуда не делись.
Здравствуйте, MxKazan, Вы писали:
ГВ>>Ну, давай поделим. Тип значения свойства и тип объекта, представляющего собой свойство. Я говорю о типе объекта, представляющего собой свойство. MK>Блин. Я не въезжаю. Что это за тип такой, "представляющий свойство"? MK>Т.е. ты берешь и объявляешь какой-то свой тип и говоришь, мол, оно есть свойство? Тогда можно в пример привести DependencyProperty
Похоже, но не совсем. DependencyProperty, это, приблизительно, HiddenSmartFunc из моего примера. Тогда как тип "представляющий свойство", это примерный аналог set/get wrapper-ов для экземпляра DependencyProperty. В моём примере "тип, представляющий свойство" — это ни что иное, как сам класс Property, у которого должны быть переопределены два оператора: оператор присвоения значения и оператор приведения к константной ссылке. Эти переопределения нужны для синтаксического сахара, т.е. чтобы можно было писать вот так:
obj.prop = 42;
int n = obj.prop;
а не так:
obj.prop.set(42);
int n = obj.prop.get();
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, -MyXa-, Вы писали:
MX>Здравствуйте, Qbit86, Вы писали:
S>>>А конструктором копирования обязательно нужно не забыть попользоваться.
Q>>Вот не понимаю я этой фразы. Как так, не забыть?
MX>Предположу, что имеется в виду, например, передача RefCounter<HugeBitmap> в качестве параметра метода:
Передача владения в метод — не такой уж частый случай. Скорее всего, на C++ ваша функция будет выглядеть так:
void foo(bitmap const& b);
а не так:
void foo(shared_ptr<bitmap> b);
или так:
void foo(shared_ptr<bitmap> const& b);
правда ведь? Ок, пусть надо передавать именно wrapper.
MX>using (RefCounter<HugeBitmap> hugeBitmap = new RefCounter<HugeBitmap>(new HugeBitmap())) MX>{ MX> foo(hugeBitmap.Clone()); // правильно MX> //foo(hugeBitmap); // ошибка MX>} MX>[/c#]
Здравствуйте, drol, Вы писали:
ГВ>>DependencyProperty — это тоже самый обычный класс. D>Про то и базар. Так вот ещё раз повторяю вопрос: причём тут свойства-то ?
Ну как при чём? Марат (MxKazan) спросил, как я собираюсь пользоваться "отдельным типом, представляющим свойство". Я ответил.
D>Они ведь как были, так и остались конструкцией языка, независимо от потрохов set/get. И все их полезные фичи никуда не делись.
В C# — безусловно. В C++ нет языковой конструкции, в точности аналогичной C#-ным property. Но всё то же самое, что доступно свойствам C# вполне доступно и их эмуляции в C++. То есть с одной стороны мы получаем традиционный синтаксис операций присвоения и чтения значения (obj.prop = val и val = obj.prop), а с другой — можем скрыть за этими операциями всё, что захочется (полная аналогия с парой set/get).
Крме того, на C++, ИМХО, получается даже интереснее, чем на C#. Чем именно — я показал в своём примере с обобщением функции, оперирующей свойствами.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!