首先,我知道许多已发布的问题涉及该主题:1 2 3 4 5。提出的方法&为什么不:
由于填充和问题已发布1 2 3,似乎没有最佳解决方案,而是在精度,性能和代码膨胀之间进行权衡。
但是,我需要简单的方法来计算乐观(最小)内存使用量,即我想知道该对象至少占用那么多。理由是我有类型的环境拥有许多集合,有时嵌套,我想快速近似,一个对象接近,即内存中的.5 GB等。
我想出的是&我的问题:
我无法获得自动生成的字段(属性
__BackingField
)对于继承类型,虽然它适用于未继承的支持字段。我搜索了正确的BindingFlag,但找不到一个。
public static long SizeInBytes<T>(this T someObject)
{
var temp = new Size<T>(someObject);
var tempSize = temp.GetSizeInBytes();
return tempSize;
}
/// <summary>
/// A way to estimate the in-memory size af any menaged object
/// </summary>
/// <typeparam name="TT"></typeparam>
private sealed class Size<TT>
{
private static readonly int PointerSize = Environment.Is64BitOperatingSystem
? sizeof(long)
: sizeof(int);
private readonly TT _obj;
private readonly HashSet<object> _references;
public Size(TT obj)
{
_obj = obj;
_references = new HashSet<object> { _obj };
}
public long GetSizeInBytes()
{
return GetSizeInBytes(_obj);
}
private long GetSizeInBytes<T>(T obj)
{
if (obj == null) return sizeof(int);
var type = obj.GetType();
if (type.IsPrimitive)
{
switch (Type.GetTypeCode(type))
{
case TypeCode.Boolean:
case TypeCode.Byte:
case TypeCode.SByte:
return sizeof(byte);
case TypeCode.Char:
return sizeof(char);
case TypeCode.Single:
return sizeof(float);
case TypeCode.Double:
return sizeof(double);
case TypeCode.Int16:
case TypeCode.UInt16:
return sizeof(short);
case TypeCode.Int32:
case TypeCode.UInt32:
return sizeof(int);
case TypeCode.Int64:
case TypeCode.UInt64:
default:
return sizeof(long);
}
}
if (obj is decimal)
{
return sizeof(decimal);
}
if (obj is string)
{
return sizeof(char) * obj.ToString().Length;
}
if (type.IsEnum)
{
return sizeof(int);
}
if (type.IsArray)
{
long sizeTemp = PointerSize;
var casted = (IEnumerable)obj;
foreach (var item in casted)
{
sizeTemp += GetSizeInBytes(item);
}
return sizeTemp;
}
if (obj is Pointer)
{
return PointerSize;
}
long size = 0;
var t = type;
while (t != null)
{
size += PointerSize;
var fields =
t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.DeclaredOnly);
foreach (var field in fields)
{
var tempVal = field.GetValue(obj);
if (!_references.Contains(tempVal))
{
_references.Add(tempVal);
size += GetSizeInBytes(tempVal);
}
}
t = t.BaseType;
}
return size;
}
}
[编辑]
此问题产生了Nuget和cp article
答案 0 :(得分:3)
要回答关于获取字段的第三个问题,您可以可靠地获取如下所示的所有字段:
public static IEnumerable<FieldInfo> GetAllFields(Type t)
{
while (t != null)
{
foreach (FieldInfo field in t.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly))
{
yield return field;
}
t = t.BaseType;
}
}
这是有效的,因为GetFields
可以返回当前Type
的私有字段,但不能返回任何继承的私有字段;所以你需要走在每个GetFields
上调用Type
的继承链上。