[noinlining]
static int m(int n,Func<int> func,string msg){
int sum=0;
var s=Stopwatch.StartNew();
for(int i=0;i<n;i++)
sum+=func(i);
s.Stop;
print(s.Elapsed.TotalNanosecunds/n,msg);
return sum;
}
unsafe byte* ptr; // Nativememory.AllocAlligned();
long ptrAddr; //= (long)ptr;
[Benchmark(Description = "ReadUnaligned")]
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public long ReadUnaligned()
{
return Unsafe.ReadUnaligned<long>(ref buffer[position]) ;
}
[Benchmark(Description = "ReadLongFromPtrLong")]
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public long ReadLongFromPtrLong()
{
unsafe
{
return *(long*)(ptrAddr | position);
}
}
[Benchmark(Description = "ReadLongFromPtr")]
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public long ReadLongFromPtr ()
{
unsafe
{
return *(long*)( ptr + position);
}
}
var pointVar = il.DeclareLocal(typeof(Point*), true);
Point p = new Point() { X = 1 };
<b>il.Emit(OpCodes.Ldc_I8, (ulong)&p); </b>
OpCodes.Ldc_I8, (long)&p
il.Emit(OpCodes.Conv_U);
//... дальше все ок
//аналог
static unsafe void f()
{
ulong ptrp = 0x11111ffffffu; // значение будет вычислено при генерации
Point* ptr = (Point*)ptrp;
}
il.Emit(OpCode.LdStr, "HelloWorld); кладет строку, фактически только адрес на нее, строка это объект, значит должны быть команды, и для произвольного типа.
.locals init (
[0] valuetype C/Point& pinned
)
IL_0000: ldarga.s p1
IL_0002: conv.u
IL_0003: conv.u8
IL_0004: call void [System.Console]System.Console::WriteLine(uint64)
IL_0009: ldsflda valuetype C/Point C::point
IL_000e: stloc.0
IL_000f: ldloc.0
IL_0010: conv.u
IL_0011: ldfld int32 C/Point::X
IL_0016: call void [System.Console]System.Console::WriteLine(int32)
// sequence point: hidden
IL_001b: ldc.i4.0
IL_001c: conv.u
IL_001d: stloc.0
IL_001e: ret
struct Point{
public int X;
}
static Point point=new Point(){X=100};
static unsafe void f(in int r, Point p1){
ulong ptrp=(ulong)&p1;
Console.WriteLine(ptrp);
fixed(Point* ptr=&point){
Console.WriteLine((ptr )->X);
}
}
// sum(byte* arr)
// sum=0;
// for(int i=0;i<10;i++)
// sum+= arr[i];
// return sum;
// вариантик на ходу , пример 3адр кода
0: load maxReg 10
1: load IterReg , 0
2: load sumReg, 0
3: load arrReg, r1
4: branchIfLess IterReg, maxReg, "9:"
5: load valReg, [sumReg+iterReg]
6: add sumReg, valReg
7: addi iterReg, 1
8: branchIfLess r1, r2, "5:"
9: mov r1, sumReg
10: ret
byte ReadByte(int address){
if(address<0 && address>maxAddress) ____();/// что-то там
return *(byte-*)mem+address;
}
// byte ReadByte(int address)=> *(byte-*)mem+address;
Вопрос, чисто, на тему, А что можно придумать.
2. Такое в небезопасном коде в можно, с слабой типизацией делать.
Есть примеры, несколько раз сталкивался, с таким. диспетчеризацией в основном.
Определить можно по месту вызова метода. Если сюда попал то уже понятно что делать. и другие данные просто не дойдут, на совести программиста.
Или Типа объект носителя решит какой это тип будет.
Просто порой писать дженерик не хочется, когда название Класса по смыслу с типом не сочетаются. К примеру
Point<int> Point<float>
легко понимается.А если там я не знаю
User<int>
как-то непонятно выглядит.