Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> упаковка значимых типов 
:(
    Опции темы
nmn
Дата 4.12.2008, 22:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 593
Регистрация: 26.11.2005

Репутация: нет
Всего: 1



Код из C# via .NET Рихтер
Код

internal struct Point : IComparable { 
private Int32 m_x, m_y; 
// Конструктор, просто инициализирующий поля, 
 public Point(Int32 x, Int32 у){...}
// Переопределяем метод ToString, унаследованный от System.ValueType. 
public override String ToString { ... }
// Безопасная в отношении типов реализация метода CompareTo. 
public Int32 CompareTo(Point other) {...} 
// Реализация метода CompareTo интерфейса IComparable. 
public Int32 CompareTo(Object o) {...}
}


Код

public static class Program { 
public static void Main() { 
 // Создаем в стеке два экземпляра Point. 
 Point p1 = new Point(0, 10); 
 Point p2 = new Point(0, 20); 
 // p1 HE пакуется для вызова ToString (виртуальный метод). 
 Console.WriteLine(p1.ToString());// "A0, 10)" 
 // p ПАКУЕТСЯ для вызова GetType (невиртуальный метод). 
 Console.WriteLine(p1.GetType());// "Point" 
}
}


Вопрос: почему происходит упаковка в 9 строчке? Почему без нее нельзя?
PM Skype   Вверх
PashaPash
Дата 4.12.2008, 22:50 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 9
Всего: 49



nmn, Код System.Object ожидает this указывающий на объект в куче, и для вызова нужна упакованная структура.
Метод Point.ToString точно знает что он работает над куском стека. Кроме того, компилятор знает что у Point нет наследников, читерит - заменяет callvirt на constrained. Point callvirt. Т.е. фактически тут не вызов виртуального метода, а простой вызов метода структуры, причем и вызывающая и вызываемая сторона знают что работают со структурой, а не с reference type - поэтому общаются без упаковки.


--------------------
PM MAIL WWW   Вверх
nmn
Дата 4.12.2008, 22:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 593
Регистрация: 26.11.2005

Репутация: нет
Всего: 1



а в ToString разве никакого указателя на экземпляр Point не передается? откуда ToString знает для какого экземпляра ее вызвали?
PM Skype   Вверх
nmn
Дата 4.12.2008, 23:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 593
Регистрация: 26.11.2005

Репутация: нет
Всего: 1



получается что если
Код

struct Test
{
public override string ToString()
{
return base.ToString();
}
}

class m
{
 static void Main()
{
Test c=new Test();
Console.WriteLine(c.ToString());
}
}

то для вызова ToString необходимо упаковать c?
PM Skype   Вверх
PashaPash
Дата 5.12.2008, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 9
Всего: 49



nmn, для вызова c.ToString - нет, тут прямой вызов (constrained callvirt). Для вызова base.ToString - да, нужна упаковка. Посмотри сам ildasm-ом или рефлектором на код Test.ToString:
Код

.method public hidebysig virtual instance string 
        ToString() cil managed
{
  // Code size       22 (0x16)
  .maxstack  1
  .locals init ([0] string CS$1$0000)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldobj      Test
  IL_0007:  box        Test
  IL_000c:  call       instance string [mscorlib]System.ValueType::ToString()
  IL_0011:  stloc.0
  IL_0012:  br.s       IL_0014
  IL_0014:  ldloc.0
  IL_0015:  ret
} // end of method Test::ToString



--------------------
PM MAIL WWW   Вверх
nmn
Дата 5.12.2008, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 593
Регистрация: 26.11.2005

Репутация: нет
Всего: 1



ладно с боксингом вроде бы понятно: упаковка происходит при вызове методов, не реализуемых данным типом?
а вот каким образом ToString получает доступ к локальным переменным типа при отсутствии упаковки?
PM Skype   Вверх
PashaPash
Дата 5.12.2008, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 9
Всего: 49



nmn
Код

.method public hidebysig instance void  test() cil managed
{
  // Code size       16 (0x10)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  dup
  IL_0003:  ldfld      int32 ConsoleApplication10.PointStruct::localVar
  IL_0008:  ldc.i4.1
  IL_0009:  add
  IL_000a:  stfld      int32 ConsoleApplication10.PointStruct::localVar
  IL_000f:  ret
} // end of method PointStruct::test

ldarg.0 в и случае структуры, и в случае reference type загружает в стек адрес объекта. В документации сказано что value type копируется, но отладчик показывает обратное. Ну и дальше идет обычная работа через ldfld/stfld. Все дело в том, что компилятор и jit точно знают тип объекта, на который указывает this (arg 0), и могут в любой момент определить, надо ли боксить, или можно работать с ним напрямую.


--------------------
PM MAIL WWW   Вверх
nmn
Дата 5.12.2008, 22:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 593
Регистрация: 26.11.2005

Репутация: нет
Всего: 1



можно меня ссылкой осчастливить на описание il инструкций?
PM Skype   Вверх
PashaPash
Дата 6.12.2008, 01:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 9
Всего: 49





--------------------
PM MAIL WWW   Вверх
nmn
Дата 8.12.2008, 02:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 593
Регистрация: 26.11.2005

Репутация: нет
Всего: 1



Код

static Type myGetType<t>(t o)
        {
            return o.GetType();
        }


Код

.method private hidebysig static class [mscorlib]System.Type 
        myGetType<t>(!!t o) cil managed
{
  // Code size       14 (0xe)
  .maxstack  8
  IL_0000:  ldarga.s   o
  IL_0002:  constrained. !!t
  IL_0008:  callvirt   instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
  IL_000d:  ret
} // end of method Program::myGetType


Почему не происходит упаковка o? ведь o может быть значимым типом

вот тут происходит:

Код

static void Main(string[] args)
        {
            Type t = (123).GetType();
            Console.WriteLine(t.Name);
            Console.Read();
        }


Код

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       31 (0x1f)
  .maxstack  1
  .locals init ([0] class [mscorlib]System.Type t)
  IL_0000:  ldc.i4.s   123
  IL_0002:  box        [mscorlib]System.Int32
  IL_0007:  call       instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
  IL_000c:  stloc.0
  IL_000d:  ldloc.0
  IL_000e:  callvirt   instance string [mscorlib]System.Reflection.MemberInfo::get_Name()
  IL_0013:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0018:  call       int32 [mscorlib]System.Console::Read()
  IL_001d:  pop
  IL_001e:  ret
} // end of method Program::Main


Это сообщение отредактировал(а) nmn - 8.12.2008, 03:04
PM Skype   Вверх
PashaPash
Дата 8.12.2008, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 9
Всего: 49



nmn, потому что на самом деле упаковка происходит. Почитай хелп по constrained - в примере с ToString он не упаковавал, а тут - неявно упаковывает.
Вообще, boxing - внутренний механихм .net, который работает относительно прозрачно для разработчика. Про него вообще нужно вспоминать только если черезмерное его использование вызывает проблемы с производительностью. А время на упаковку одного объекта - 0.000 секунд.


--------------------
PM MAIL WWW   Вверх
nmn
Дата 8.12.2008, 16:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 593
Регистрация: 26.11.2005

Репутация: нет
Всего: 1



Цитата(PashaPash @  8.12.2008,  09:20 Найти цитируемый пост)
а тут - неявно упаковывает


http://msdn.microsoft.com/en-us/library/sy...onstrained.aspx
т.е работает вот это?
Код

If thisType is a value type and thisType does not implement method then ptr is dereferenced, boxed, and passed as the 'this' pointer to the callvirt  method instruction. 



Это сообщение отредактировал(а) nmn - 8.12.2008, 16:58
PM Skype   Вверх
PashaPash
Дата 8.12.2008, 17:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 9
Всего: 49



nmn, да. на практике это значит что до jit-компиляции неизвесно будет boxing или нет.


--------------------
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, Partizan, PashaPash.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | .NET для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0515 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.