Если вы не заметили, статья называется “C# делегаты изнутри…”, это вроде как главное, если, конечно, вы мне разрешите, что-то решить по поводу моей статьи. Ну ладно, замнем для ясности.
Хм, перечитал по новой и, совсем ничего не нашел про то, как делегат в C# устроен изнутри, т.е. как делегат выглядит на уровне CIL и что происходит в CLR\Mono когда оно выполняетт соответсвующие инструкции. Да и весь рассказ про делегаты в C# сводится к предложению: "Там делегаты определяются с помощью ключевого слова delegate".
И да, коль я перечитал еще раз статью, хотелось прокомментировать интересный момент:
Есть еще одна сложность с пониманием делегатов. Мы привыкли что в переменных у нас хранятся данные, а в переменной типа Делегат мы сохраняем функцию, а функция — это блок кода.
А вы думали почему указатели на функцию и методы в Си++ такие как есть?
Да ничем, более того это единственный вариант, когда можно реализовать кастование dyn объектов пока не завезли в стабильную ветку. Но то, что в ООП называется интерфейсами в Расте возможно только через dyn объекты, а их не для каждого типажа можно создать.
trait TraitA{
fn a(); // колючевое слово self отсутствует
}
trait TraitB: TraitA{
fn b(&self);
}
trait TraitC {
fn c (&self);
}
struct A{
}
impl TraitA for A{}
impl TraitB for A{}
impl TraitC for A{}
struct B{
}
impl TraitC for B {}
Вот в такой конструкции вы не сможете создать dyn TraitA, а из-за это не может создать dyn TraitB, также мы не можем создать dyn TraitC для типа А, но можем для типа B.
Нет, при реализации трейта вы не можете использовать методы из реализации соседнего трейта, только методы и данные самого типа. Т.е. если учть продолжить пример у вас будет:
trait TraitA{
fn a(&self);
}
trait TraitB: TraitA{
fn b(&self);
}
struct My
{
d: i32,
}
impl My
{
fn a_p(&self) {
}
}
impl TraitA for My{
fn a(&self){
self.a_p());
}
}
impl TraitB for My{
fn b(&self){
self.a_p());
// и только так, вы не можете сделать self.a()
}
}
Ключевое слово dyn достаточно хитрое. По факту оно создает новый тип "dyn Trait", который содержит указатель на данные и указатель на методы. Но, помимоо этого вы можете сделать:
impl dyn Trait
{
pub fn my_fn(&self) {
}
}
У типажей нету механизма наследования когда вы пишите:
trait TraitA{}
trait TraitB: TraitA{}
Вы не наследуете TraitB от TraitA, вы накладывает ограничения, чтобы тип определяющий TraitB также определял бы и TraitA. И это две большие разницы.
Это не совсем корректный вопрос. Да, некоторые из тех проверок которые в Си++ проходится делать в рантайме, в Расте можно делать на этапе компиляции. Но вот в чем прикол: понятие "объект" у вас при этом исчезает. И если во многих случаях без него можно обойтись не потеряв производительности (хотя придется и поломать голову), то в некоторых областях (тот же пользовательский интерфейс) это доставлет массу проблем, которые, вполне возможно, выливаются в потерю производительсноти.
Мысль такая: "Если перевыпуск Visa и MasterCard был свзяан с безопасностью, то в условиях когда они не перевыпускаются, то м.б. это и оправдано". Однако видите здесь сколько "м.б." и "если"? Вот отсюда и вопрос
В твердых телах распространение звука имеет принципиально иной механизм, чем в газе. В газе больше роль имеет средняя скорость частиц, которая зависит от массы молекулы и температуры.
Мой опыт показывает, что в 999 случаев из 1000 необходимость в тестировании внутренних методов класса говорит о неправильной декомпозиции. В очень редких случаях, это действительно нужно, но эти тесты уже что-то среднее между интеграционными и юнит-тестами.
Гн вижу ничего плохого в том чтобы похвалить хорошую статью, как. впрочем и покритиковать, если есть за что.
Хм, перечитал по новой и, совсем ничего не нашел про то, как делегат в C# устроен изнутри, т.е. как делегат выглядит на уровне CIL и что происходит в CLR\Mono когда оно выполняетт соответсвующие инструкции. Да и весь рассказ про делегаты в C# сводится к предложению: "Там делегаты определяются с помощью ключевого слова delegate".
И да, коль я перечитал еще раз статью, хотелось прокомментировать интересный момент:
А вы думали почему указатели на функцию и методы в Си++ такие как есть?
А зачем bind когда есть лямбды?
Спасибо, мне казалось что добавит ограничения и на сам тип. Был не прав. Но в любом случае вы не сможете сделать let a: &dyn TraitA = &A{};
Соглашусь со всем комменатрием кроме этого предложения. UB в С++, как и в Unsafe Rust контринтутивен и хрен редьки не слаще.
Мешает то, что тип А реализует TraitA. Этой ситуации не может быть в принципе при наследовании.
Да ничем, более того это единственный вариант, когда можно реализовать кастование dyn объектов пока не завезли в стабильную ветку. Но то, что в ООП называется интерфейсами в Расте возможно только через dyn объекты, а их не для каждого типажа можно создать.
Вот в такой конструкции вы не сможете создать dyn TraitA, а из-за это не может создать dyn TraitB, также мы не можем создать dyn TraitC для типа А, но можем для типа B.
Значит уже затащили в стабильную ветку, где-то еще год назад такой фокус не проходил. Запаривало страшно.
Нет, при реализации трейта вы не можете использовать методы из реализации соседнего трейта, только методы и данные самого типа. Т.е. если учть продолжить пример у вас будет:
Ключевое слово dyn достаточно хитрое. По факту оно создает новый тип "dyn Trait", который содержит указатель на данные и указатель на методы. Но, помимоо этого вы можете сделать:
У типажей нету механизма наследования когда вы пишите:
Вы не наследуете TraitB от TraitA, вы накладывает ограничения, чтобы тип определяющий TraitB также определял бы и TraitA. И это две большие разницы.
Нет, они что-то сродни концептам.
Это не совсем корректный вопрос. Да, некоторые из тех проверок которые в Си++ проходится делать в рантайме, в Расте можно делать на этапе компиляции. Но вот в чем прикол: понятие "объект" у вас при этом исчезает. И если во многих случаях без него можно обойтись не потеряв производительности (хотя придется и поломать голову), то в некоторых областях (тот же пользовательский интерфейс) это доставлет массу проблем, которые, вполне возможно, выливаются в потерю производительсноти.
Мысль такая: "Если перевыпуск Visa и MasterCard был свзяан с безопасностью, то в условиях когда они не перевыпускаются, то м.б. это и оправдано". Однако видите здесь сколько "м.б." и "если"? Вот отсюда и вопрос
Интересно, а с чем был связан постоянный перевыпуск карт этих систем?
В твердых телах распространение звука имеет принципиально иной механизм, чем в газе. В газе больше роль имеет средняя скорость частиц, которая зависит от массы молекулы и температуры.
Молекулы и атом целиком уже классический объект.
Валве тоже, столкнувшись с обвалом продаж.
Мой опыт показывает, что в 999 случаев из 1000 необходимость в тестировании внутренних методов класса говорит о неправильной декомпозиции. В очень редких случаях, это действительно нужно, но эти тесты уже что-то среднее между интеграционными и юнит-тестами.
По идее могу, аксиома выбора мне это позволяет..
UPD Протупил.
Есть такое понятие, как супернатуральное число.