Premièrement, je suis au courant de nombreuses questions posées sur le sujet: 1 2 3 4 5 . Les approches proposées & pourquoi pas:
En raison du remplissage et des problèmes publiés 1 2 3 , semble-t-il, il n’existe pas de solution optimale, mais plutôt un compromis entre précision, performances et gabarit de code.
Cependant, j’avais besoin d’une méthode simple pour compter l’utilisation de mémoire optimiste (minimum), c’est-à-dire que je veux savoir que l’object occupe au moins autant . La raison en est que j’ai dans l’environnement des types possédant plusieurs collections, parfois nestedes, et que je veux me rapprocher rapidement, qu’un object se rapproche de 0,5 Go en mémoire, etc.
Il y a ce que je suis venu avec et mes questions:
Je ne parviens pas à obtenir les champs générés automatiquement (propriété __BackingField
) pour le type hérité, alors que cela fonctionne __BackingField
pour les champs de sauvegarde non hérités. J’ai cherché le BindingFlag approprié, mais je n’ai pas pu en trouver un.
public static long SizeInBytes(this T someObject) { var temp = new Size(someObject); var tempSize = temp.GetSizeInBytes(); return tempSize; } /// /// A way to estimate the in-memory size af any menaged object /// /// private sealed class Size { private static readonly int PointerSize = Environment.Is64BitOperatingSystem ? sizeof(long) : sizeof(int); private readonly TT _obj; private readonly HashSet _references; public Size(TT obj) { _obj = obj; _references = new HashSet { _obj }; } public long GetSizeInBytes() { return GetSizeInBytes(_obj); } private long GetSizeInBytes(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 ssortingng) { return sizeof(char) * obj.ToSsortingng().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; } }
[MODIFIER]
Cette question a abouti à l’ article de Nuget et cp
Pour répondre à votre troisième question sur l’obtention de champs, vous pouvez obtenir de manière fiable tous les champs dans un type comme celui-ci:
public static IEnumerable 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; } }
Cela fonctionne car GetFields
peut renvoyer les champs privés du Type
actuel, mais pas les champs privés hérités. vous devez donc parcourir la chaîne d’inheritance en appelant GetFields
sur chaque Type
.