public static (FieldInfo fieldInfo, int offset)[] GetFieldOffsets(Type t)
{
var fields = t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
Func fieldOffsetInspector = GenerateFieldOffsetInspectionFunction(fields);
var instance = CreateInstance(t);
var addresses = fieldOffsetInspector(instance);
if (addresses.Length == 0)
{
return Array.Empty<(FieldInfo, int)>();
}
var baseLine = addresses.Min();
// Converting field addresses to offsets using the first field as a baseline
return fields
.Select((field, index) => (field: field, offset: (int)(addresses[index] - baseLine)))
.OrderBy(tuple => tuple.offset)
.ToArray();
}
class ByteAndInt
{
public byte b;
public int n;
}
Console.WriteLine(
string.Join("\r\n",
InspectorHelper.GetFieldOffsets(typeof(ByteAndInt))
.Select(tpl => $"Field {tpl.fieldInfo.Name}: starts at offset {tpl.offset}"))
);
输出是:
Field n: starts at offset 0
Field b: starts at offset 4
struct SizeComputer
{
public T dummyField;
public int offset;
}
public static int GetSizeOfValueTypeInstance(Type type)
{
Debug.Assert(type.IsValueType);
var generatedType = typeof(SizeComputer<>).MakeGenericType(type);
// The offset of the second field is the size of the 'type'
var fieldsOffsets = GetFieldOffsets(generatedType);
return fieldsOffsets[1].offset;
}
public static int GetSizeOfReferenceTypeInstance(Type type)
{
Debug.Assert(!type.IsValueType);
var fields = GetFieldOffsets(type);
if (fields.Length == 0)
{
// Special case: the size of an empty class is 1 Ptr size
return IntPtr.Size;
}
// The size of the reference type is computed in the following way:
// MaxFieldOffset + SizeOfThatField
// and round that number to closest point size boundary
var maxValue = fields.MaxBy(tpl => tpl.offset);
int sizeCandidate = maxValue.offset + GetFieldSize(maxValue.fieldInfo.FieldType);
// Rounding the size to the nearest ptr-size boundary
int roundTo = IntPtr.Size - 1;
return (sizeCandidate + roundTo) & (~roundTo);
}
public static int GetFieldSize(Type t)
{
if (t.IsValueType)
{
return GetSizeOfValueTypeInstance(t);
}
return IntPtr.Size;
}
我们有足够的信息在运行时获取任何类型实例的正确布局信息。
在运行时检查值类型布局
我们从值类型开始,并检查以下结构:
public struct NotAlignedStruct
{
public byte m_byte1;
public int m_int;
public byte m_byte2;
public short m_short;
}
[StructLayout(LayoutKind.Auto)]
public struct NotAlignedStructWithAutoLayout
{
public byte m_byte1;
public int m_int;
public byte m_byte2;
public short m_short;
}
internal struct ByteWrapper
{
public byte b;
}
internal class ClassWithByteWrappers
{
public ByteWrapper bw1;
public ByteWrapper bw2;
public ByteWrapper bw3;
}
原题链接:#137 Single Number II
要求:
给定一个整型数组,其中除了一个元素之外,每个元素都出现三次。找出这个元素
注意:算法的时间复杂度应为O(n),最好不使用额外的内存空间
难度:中等
分析:
与#136类似,都是考察位运算。不过出现两次的可以使用异或运算的特性 n XOR n = 0, n XOR 0 = n,即某一
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given an encoded message containing digits, det