Re[2]: Зачем?
От: Аноним  
Дата: 07.10.05 07:55
Оценка: 1 (1)
Вот именно. А как раз в этом CLS и нету МН именно по вопросам совместимости.
-----------------------
Вы действительно считаете что МН в CLS нету ради совместимости с VB в котором МН не было и нету?
-----
Нулевое оформления постов благодаря Opere.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[2]: Зачем?
От: GlebZ Россия  
Дата: 07.10.05 10:46
Оценка:
Здравствуйте, DenisCh, Вы писали:

DC>Объясняется тем, что c# компилирует в MSIL. Туда же компилируют и VB#, и другие. А в этих других _нет_ множественного наследования. А для использования C#-класса в VB#-классе они жолжны быть совместимы. Вон есть managedC++. попробуй на нём сделать множественное наследование...

C++/CLI — на здоровье. И работает. Для MSIL — множественное наследование не проблема. Это проблема CLS.

С уважением, Gleb.
Re: Зачем?
От: GlebZ Россия  
Дата: 07.10.05 10:50
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

Например, допустим мн есть:

public class A
{
int _a;
public A(int a)
{
_a=1;
}
virtual void Init(){_a+=1;}
}

public class B
{
int _b;
public B()
{
Init();
}
virtual void Init(){_b=1;}
}

public class C:A,B
{
public C(int i):base(i)
{
}
override void Init(){base.Init();}
}

С с=new C(1);

Здесь сразу же несколько ошибок. Если компилятор такое пропустит, то вообще не локализуешь ошибку. Но допустим компилятор дает ошибки на подобную ситуацию.
А теперь представь что класс A находится в другой сборке. При компиляции объекта С — у него отсутствовала функция Init. То есть, конфликта как такового нету. Потом сборку с объектом A перекомпилили, и добавили метод Init.
Для концептуально-выверенного языка, который построен для того чтобы уменьшать ошибки программистов такие выпендрежи делать нельзя. Проблемы решить можно. Пуская даже криво, но можно. Вобщем, кроме заметного усложнения, особых плюсов не получишь. А это не может быть совместимо с идеалогией C# и CLS.

С уважением, Gleb.
Re[3]: Зачем?
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.10.05 14:10
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>C++/CLI — на здоровье. И работает. Для MSIL — множественное наследование не проблема. Это проблема CLS.

Хм. Лично мне казалось, что невозможно в терминах MSIL написать такой класс, объекты которого бы успешно кастилисм к двум различным классам.
Имхо, все реализации MI в Net суть хаки. И компилер либо прячет такие классы от публики, либо выпрямляет иерархию, либо еще как утаптывает это все в стандартные рамки.
... << RSDN@Home 1.1.4 stable rev. 510>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Зачем?
От: GlebZ Россия  
Дата: 07.10.05 19:07
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, GlebZ, Вы писали:


GZ>>C++/CLI — на здоровье. И работает. Для MSIL — множественное наследование не проблема. Это проблема CLS.

S>Хм. Лично мне казалось, что невозможно в терминах MSIL написать такой класс, объекты которого бы успешно кастилисм к двум различным классам.
S>Имхо, все реализации MI в Net суть хаки. И компилер либо прячет такие классы от публики, либо выпрямляет иерархию, либо еще как утаптывает это все в стандартные рамки.
Это не только твое, присоединяюсь. Основные проблемы в метаданных. Ну не держат они множественное наследование. Из-за этого, там такая пурга творится, что мама не балуйся. Но на этапе компиляции никаких проблем нет. JIT мало понимает кто перед ним — метод интерфейса или метод объекта. Он это узнает по метаданным. И получается такая фигня, для интерфейсов, которые поддерживают множественное наследование он генерит следующий код(заглядывать в ассемблер сейчас не буду, да и к тому-же для многих непонятно будет).
Для MSIL такая конструкция callvirt instance bla-bla которая в случае множественного наследования без дебаггинга на ассемблер вываливается в таком виде
1. у this из виртуальной таблицы — взять указатель на виртульную таблицы конкретного интерфейса
2. взять указатель из виртуальной таблицы интерфейса указатель на функцию
3. выполнить
То есть система абсолютно аналогична unmanaged C++. Код практически всегда оптимизируется JIT до прямых вызовов. Это действительно только для неоптимизированного дебуга.(11.4.1.4 Virtual Calling Convention)
То есть компиляция при множественном наследовании есть. Она в принципе стандартна(если не говорить об оптимизациях).
Мало того, я не нашел в спецификации, где бы говорилось что callvirt опознает c кем он работает, с интерфейсом или объектом.

В спецификации(сейчас у меня только 1.1) нашел только такой интересный параграф.

callvirt, part of the CIL common type system instruction set, uses the class of an object (known only at runtime) to determine the method to be called. The instruction includes a method reference, but the particular method isn’t computed until the call actually occurs. This allows an instance of a subclass to be supplied and the method appropriate for that subclass to be invoked. The callvirt instruction is used both for instance methods and methods on interfaces. For further details, see the Common Type System specification and the CIL Instruction Set specification.


Так что хаком можно попробовать сделать множественное наследование с несколькими виртуальными таблицами. Пока времени нет.

С уважением, Gleb.

ЗЫ:Оказалось в ref классах действительно нет наследования. Для остальных злостная эмуляция.
Re[5]: Зачем?
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.10.05 19:21
Оценка:
Здравствуйте, GlebZ, Вы писали:
GZ>Это не только твое, присоединяюсь. Основные проблемы в метаданных. Ну не держат они множественное наследование. Из-за этого, там такая пурга творится, что мама не балуйся. Но на этапе компиляции никаких проблем нет. JIT мало понимает кто перед ним — метод интерфейса или метод объекта. Он это узнает по метаданным. И получается такая фигня, для интерфейсов, которые поддерживают множественное наследование он генерит следующий код(заглядывать в ассемблер сейчас не буду, да и к тому-же для многих непонятно будет).
GZ>Для MSIL такая конструкция callvirt instance bla-bla которая в случае множественного наследования без дебаггинга на ассемблер вываливается в таком виде
GZ>1. у this из виртуальной таблицы — взять указатель на виртульную таблицы конкретного интерфейса
GZ>2. взять указатель из виртуальной таблицы интерфейса указатель на функцию
GZ>3. выполнить
GZ>То есть система абсолютно аналогична unmanaged C++.
Не, тут проблема вовсе не в callvirt. Проблема в castclass. Не будет она работать с такими псевдоклассами. А с интерфейсами — будет.
... << RSDN@Home 1.1.4 stable rev. 510>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Зачем?
От: DenisCh Россия  
Дата: 10.10.05 05:05
Оценка:
Здравствуйте, AndroidLV, Вы писали:

ALV>Вот именно. А как раз в этом CLS и нету МН именно по вопросам совместимости.

ALV>Вы действительно считаете что МН в CLS нету ради совместимости с VB в котором МН не было и нету?

Это не я так считаю. Это я прочитал в одной из книжек (какой — не помню).
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: Зачем?
От: Mr. None Россия http://mrnone.blogspot.com
Дата: 10.10.05 07:39
Оценка:
Здравствуйте, Аноним, Вы писали:

Если вы имели в виду C++, то будет так

А>class CBase

А>{
А>protected int _i;

А>public: virtual void DoIt() = 0;

А>}

А>class C1 : public CBase

А>{
А>public: virtual void DoIt()
А>{
А>_i = 1;
А>}
А>}

А>class C2 : public CBase

А>{
А>public: virtual void DoIt()
А>{
А>_i = 2;
А>}
А>}

А>class C3: public C1, public C2

А>{
А>public void Do()
А>{
А> DoIt();
error C2385: ambiguous access of 'DoIt' in 'C3'
А> Console.Write(i); // ???
А>}
А>}

Поэтому в случае C++ никакой проблемы нет.
Собственно нет её и в самом множественном наследовании. А почему его нет в C# — элементарно Ватсон... В C# все классы наследуются от одного базовго класса (Object), если разрешить множественное наследование, то оно всегда будет "брильянтовым" и при такой иерархии обращение к любому методу этого класса (например, ToString) либо придётся снабжать явным квалификатором доступа (что не удобно), либо всё наследование делать виртуальными (что возможно накладно)... В MS поступили проще — запретили множественное наследование...
Почему было не сделать виртуальным только наследование от класса Object и только в случае иерархии с множественным наследованием, я не знаю. Если к этому ещё добавить автоматическую генерацию и замещение всех методов класса Object в новом классе, то никакой проблемы бы не было... Очевидно не сделали по той же причине, по которой объекты by-value гарантировано уничтожаются при выходе за пределы локальной области вызова, но при этом у них отсутсвует деструктор... Либо не успевали, либо не додумались, либо это очень сильно не ложилось в общую архитектуру системы, что решили не исправлять... Вобщем сделали не как удобно, а как велел отдел маркетинга.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.