2010-06-16 2 views
17

Существуют ли способы определения общего размера сложного объекта в .NET? Этот объект состоит из других объектов и может содержать ссылки на другие сложные объекты. Некоторые объекты, инкапсулированные этим объектом, могут быть POD, другие - нет.Способы определения размера сложного объекта в .NET?

+1

Являются ли объекты сериализуемыми? –

+0

они МОГУТ быть :) Извините за туманность, но я пытаюсь сделать этот вопрос как можно более общим. – Polaris878

+0

Что такое «POD» в контексте C#/.NET? Это термин C++ ... –

ответ

10

Что вы имеете, это не «сложный объект», это граф объектов. Чтобы определить его общий размер, вам нужно пройти этот график - начиная с некоторого корневого объекта и используя Reflection, чтобы перечислять поля ссылочных типов и извлекать их значения (и, конечно, проверять цикл).

Чтобы получить размер определенного объекта на графике, см. this answer to a related question, но обратите внимание, что это злой хак, полностью неподдерживаемый, может сломаться (и может быть уже сломан), и может привести к оплодотворению геноцида котенка в небесные сферы. Тем не менее, нет «не-хакерского» способа получения точного значения, поскольку по определению это детали реализации - вы не должны им пользоваться. И для того, чтобы узнать об использовании памяти в приложении во время отладки/профилирования, взлом достаточно хорош.

+0

Спасибо, Павел. Я понял сложности, когда задавал вопрос, мне было просто интересно узнать, кто-то уже создал обход объекта, который подсчитал это :) – Polaris878

1

Дать System.Runtime.InteropServices.Marshal.SizeOf() выстрел.

+0

'Marshal.SizeOf()' не может принимать во внимание размер подобъектов. – drharris

+0

Имейте в виду, что это критически важная функция безопасности, поэтому, к сожалению, она не работает во многих контекстах. –

+1

Он дает размер маршалированного представления объекта, что не совсем одно и то же. –

2

Tricky ...

Что делать, если два объекта указывают на одной и той же переменной строки. Кто «владеет» строкой? Мне кажется, вам нужно смоделировать сборку мусора, чтобы получить верный ответ. Не совсем легкий вес.

+0

Строка здесь не является хорошим примером, потому что она неизменна. –

+2

@Paul: какова непреложность в этом? Дело в том, что объект может содержать ссылку на строку, которая была предоставлена ​​ему извне (например, имя файла). Связана ли эта строка с объектом или нет? Должен ли он считаться частью его размера или нет? –

4

Проще говоря, нет способа узнать. Предполагая, что все объекты сериализуемы, вы можете использовать BinaryFormatter для их сериализации в двоичный блок, а затем прочитать размер этого. Однако это будет включать некоторые метаданные и раздуть фактический размер объекта (но это будет разумная оценка).

Для типов значений вы должны использовать Marshal.SizeOf(), только он не принимает во внимание любые подобъекты. Он будет вычислять любой внутренний ссылочный тип как размер указателя на него.

Отражение - это еще один способ, но не будет раскрывать никаких частных членов, занимающих память. Поэтому, если я не ошибаюсь, нет способа сделать это правильно.

1

Ранее в других ответили на StackOverflow:

Find size of object instance in bytes in c#

Вам необходимо ввести небезопасный код (из-за операции указателя, необходимых для этого) - код выглядит следующим образом:

static unsafe int CalcSize(object obj) 
{ 
    RuntimeTypeHandle th = obj.GetType().TypeHandle; 
    int size = *(*(int**)&th + 1); 
    return size; 
} 

Также помните, для отметки параметров проекта (Project-> Build tab) для «Разрешить небезопасный код».