Unsafe.AsSpan: Span рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреЛ рдХреИрд╕реЗ рдмрджрд▓реЗрдВ?


C# рдПрдХ рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдк рд╕реЗ рд▓рдЪреАрд▓реА рднрд╛рд╖рд╛ рд╣реИред рдЙрд╕ рдкрд░ рдЖрдк рди рдХреЗрд╡рд▓ рдмреИрдХрдПрдВрдб рдпрд╛ рдбреЗрд╕реНрдХрдЯреЙрдк рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред рдореИрдВ рд╡реИрдЬреНрдЮрд╛рдирд┐рдХ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП C# рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рдЬреЛ рднрд╛рд╖рд╛ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рдЙрдкрдХрд░рдгреЛрдВ рдкрд░ рдХреБрдЫ рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐ netcore netstandard2.0 рдПрдЬреЗрдВрдбрд╛ рдкрд░ рд╣реИ (рдпрд╣ рдорд╛рдирддреЗ рд╣реБрдП рдХрд┐ netstandard2.0 рдмрд╛рдж рджреЛрдиреЛрдВ рднрд╛рд╖рд╛рдУрдВ рдФрд░ рд░рдирдЯрд╛рдЗрдо рдХреА рдЕрдзрд┐рдХрд╛рдВрд╢ рд╕реБрд╡рд┐рдзрд╛рдПрдБ netframework рдХреЛ netframework рдирд╣реАрдВ netframework ), рдореИрдВ рд╡рд┐рд░рд╛рд╕рдд рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦрддрд╛ рд╣реВрдВред


рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рдПрдХ рдЧреИрд░-рд╕реНрдкрд╖реНрдЯ (рд▓реЗрдХрд┐рди рд╢рд╛рдпрдж рд╡рд╛рдВрдЫрд┐рдд?) Span<T> рдЖрд╡реЗрджрди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддрд╛ рд╣реВрдВ Span<T> рдФрд░ clr рдХреА рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдХреЗ рдХрд╛рд░рдг netframework рдФрд░ netframework рдореЗрдВ Span<T> рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмреАрдЪ рдХрд╛ рдЕрдВрддрд░ред


рдЕрд╕реНрд╡реАрдХрд░рдг рез

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдХреЛрдб рд╕реНрдирд┐рдкреЗрдЯ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдХреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╕рд╛рдзрди рдирд╣реАрдВ рд╣реИрдВред


рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди (рджреВрд░ рдХреА рдХреМрдбрд╝реА?) рд╕рдорд╕реНрдпрд╛ рдмрд▓реНрдХрд┐ рдПрдХ рд╕рдмреВрдд рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рд╣реИред
рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ, рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдХреЗ, рдЖрдк рдЗрд╕реЗ рдЕрдкрдиреЗ рдЬреЛрдЦрд┐рдо рдФрд░ рдЬреЛрдЦрд┐рдо рдкрд░ рдХрд░рддреЗ рд╣реИрдВред


рдЕрд╕реНрд╡реАрдХрд░рдг реи

рдореБрдЭреЗ рдкреВрд░рд╛ рдпрдХреАрди рд╣реИ рдХрд┐ рдХрд╣реАрдВ рди рдХрд╣реАрдВ, рдХрд┐рд╕реА рди рдХрд┐рд╕реА рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдШреБрдЯрдиреЗ рдореЗрдВ рдХрд┐рд╕реА рдХреЛ рдЧреЛрд▓реА рдорд╛рд░ рджреЗрдЧрд╛ ред


C# рдореЗрдВ рдЯрд╛рдЗрдк рд╕реЗрдлреНрдЯреА рдХреЗ рдХрд╛рд░рдг рдХреБрдЫ рднреА рдЕрдЪреНрдЫрд╛ рд╣реЛрдиреЗ C# рд╕рдВрднрд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИред


рд╕реНрдкрд╖реНрдЯ рдХрд╛рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рд╕рднреА рд╕рдВрднрд╛рд╡рд┐рдд рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдЗрд╕ рдХреЛрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рдХрд┐рдпрд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдкрд░рд┐рдгрд╛рдо рдЖрд╢рд╛рдЬрдирдХ рджрд┐рдЦрддреЗ рд╣реИрдВред


рдореБрдЭреЗ Span<T> рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИ?


Spen рдЖрдкрдХреЛ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд░реВрдк рдореЗрдВ unmanaged рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╡рдВрдЯрди рдХреА рд╕рдВрдЦреНрдпрд╛ рдХрдо рд╣реЛ рдЬрд╛рддреА рд╣реИред рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ BCL netframework рдореЗрдВ рд╕реНрдкреИрди рдХрд╛ рд╕рдорд░реНрдерди рд▓рдЧрднрдЧ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрдиреБрдкрд╕реНрдерд┐рдд рд╣реИ, System.Memory , System.Buffers рдФрд░ System.Runtime.CompilerServices.Unsafe рдХрд╛ System.Memory рдХрд░рдХреЗ рдХрдИ рдЙрдкрдХрд░рдг рдкреНрд░рд╛рдкреНрдд рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдореЗрд░реА рд╡рд┐рд░рд╛рд╕рдд рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рд╕реНрдкреИрди рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕реАрдорд┐рдд рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореИрдВрдиреЗ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕реНрдкрд╖реНрдЯ рдЙрдкрдпреЛрдЧ рдкрд╛рдпрд╛, рдЬрдмрдХрд┐ рдкреНрд░рдХрд╛рд░ рдХреА рд╕реБрд░рдХреНрд╖рд╛ рдкрд░ рдереВрдХрдирд╛ред
рдпрд╣ рдЖрд╡реЗрджрди рдХреНрдпрд╛ рд╣реИ? рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдореИрдВ рдПрдХ рд╡реИрдЬреНрдЮрд╛рдирд┐рдХ рдЙрдкрдХрд░рдг рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реВрдВред рдпреЗ рдЫрд╡рд┐рдпрд╛рдВ рд╣реИрдВ, рдЬреЛ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ, T[] рдХреА рдПрдХ рд╕рд░рдгреА рд╣реИрдВ, рдЬрд╣рд╛рдВ T , unmanaged рдЖрджрд┐рдо рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП Int32 (рдЙрд░реНрдл int )ред рдЗрди рдЫрд╡рд┐рдпреЛрдВ рдХреЛ рдбрд┐рд╕реНрдХ рдкрд░ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХреНрд░рдордмрджреНрдз рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореБрдЭреЗ рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдк рд╕реЗ рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╡рд┐рд░рд╛рд╕рдд рдкреНрд░рд╛рд░реВрдк рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ 1981 рдореЗрдВ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рддрдм рд╕реЗ рдереЛрдбрд╝рд╛ рдмрджрд▓ рдЧрдпрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рд╛рд░реВрдк рдХреА рдореБрдЦреНрдп рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдмрд┐рдЧрдЗрдВрдбрд┐рдпрди ред рдЗрд╕ рдкреНрд░рдХрд╛рд░, T[] рдПрдХ рдЕрд╕рдореНрдкреАрдбрд┐рдд рд╕рд░рдгреА рдХреЛ рд▓рд┐рдЦрдиреЗ (рдпрд╛ рдкрдврд╝рдиреЗ) рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреА рд╕рдорд╛рдкреНрддрд┐ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рддреБрдЪреНрдЫ рдХрд╛рд░реНрдпред
рдХреБрдЫ рд╕реНрдкрд╖реНрдЯ рд╕рдорд╛рдзрд╛рди рдХреНрдпрд╛ рд╣реИрдВ?


  1. рд╣рдо рд╕рд░рдгреА T[] рдкрд░ рдкреБрдирд░рд╛рд╡реГрддрд┐ рдХрд░рддреЗ рд╣реИрдВ, BitConverter.GetBytes(T) рдХреЙрд▓ рдХрд░реЗрдВ, рдЗрди рдХреБрдЫ рдмрд╛рдЗрдЯреНрд╕ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░реЗрдВ, рд▓рдХреНрд╖реНрдп рд╕рд░рдгреА рдореЗрдВ рдХреЙрдкреА рдХрд░реЗрдВред
  2. рд╣рдо рд╕рд░рдгреА T[] рдкрд░ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд░рддреЗ рд╣реИрдВ, new byte[] {(byte)((x & 0xFF00) >> 8), (byte)(x & 0x00FF)}; (рдбрдмрд▓-рдмрд╛рдЗрдЯ рдкреНрд░рдХрд╛рд░ рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП), рд▓рдХреНрд╖реНрдп рд╕рд░рдгреА рдкрд░ рд▓рд┐рдЦреЗрдВред
  3. * рд▓реЗрдХрд┐рди T[] рдПрдХ рд╕рд░рдгреА рд╣реИ? рддрддреНрд╡ рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рд╣реИрдВ, рд╣реИ рдирд╛? рддреЛ рдЖрдк рд╕рднреА рддрд░рд╣ рд╕реЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, Buffer.BlockCopy(intArray, 0, byteArray, 0, intArray.Length * sizeof(int)); ред рд╡рд┐рдзрд┐ рд╕рд░рдгреА рдХреЛ рдЪреЗрдХрд┐рдВрдЧ рдкреНрд░рдХрд╛рд░ рдХреА рдЕрдирджреЗрдЦреА рдХрд░ рд╕рд░рдгреА рдХреЛ рдХреЙрдкреА рдХрд░рддреА рд╣реИред рдпрд╣ рдХреЗрд╡рд▓ рд╕реАрдорд╛рдУрдВ рдФрд░ рдЖрд╡рдВрдЯрди рдХреЛ рдпрд╛рдж рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИред рд╣рдо рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдмрд╛рдЗрдЯреНрд╕ рдХреЛ рдорд┐рд▓рд╛рддреЗ рд╣реИрдВред
  4. * рд╡реЗ рдХрд╣рддреЗ рд╣реИрдВ рдХрд┐ C# (C++)++ ред рдЗрд╕рд▓рд┐рдП, рд╕рдХреНрд╖рдо /unsafe , fixed(int* p = &intArr[0]) byte* bPtr = (byte*)p; рдФрд░ рдЕрдм рдЖрдк рд╕реНрд░реЛрдд рд╕рд░рдгреА рдХреЗ рдмрд╛рдЗрдЯ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рджреМрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рдордХреНрдЦреА рдкрд░ рдзреАрд░рдЬ рдХреЛ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдкреВрд░реА рдирдИ рдмрд╛рдЗрдЯ рд╕рд░рдгреА рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдП рдмрд┐рдирд╛ рдбрд┐рд╕реНрдХ ( stackalloc byte[] рдпрд╛ ArrayPool<byte>.Shared ) рдХреЛ рдЗрдВрдЯрд░рдореАрдбрд┐рдПрдЯ рдмрдлрд░ рдХреЗ рд▓рд┐рдП рдмреНрд▓реЙрдХ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдмрд┐рдВрджреБ 4 рдЖрдкрдХреЛ рд╕рднреА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди unsafe рд╕рдВрджрд░реНрдн рдФрд░ рд╕рдВрдХреЗрдд рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рд╕реНрдкрд╖реНрдЯ рдЙрдкрдпреЛрдЧ рдХрд┐рд╕реА рддрд░рд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рд╣реИред рдлрд┐рд░ Span<T> рд╣рдорд╛рд░реА рд╕рд╣рд╛рдпрддрд╛ рдХреЗ рд▓рд┐рдП рдЖрддрд╛ рд╣реИред


Span<T>


Span<T> рдХреЛ рддрдХрдиреАрдХреА рд░реВрдк рд╕реЗ рд╕реНрдореГрддрд┐ рдмрд┐рдВрджреБрдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдХрд░рдг рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬреИрд╕реЗ рдХрд┐ рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛, рд╕реНрдореГрддрд┐ рдореЗрдВ рд╕рд░рдгреА рдХреЛ "рдареАрдХ" рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рдирд╛ред рд╕рд░рдгреА рд╕реАрдорд╛рдУрдВ рдХреЗ рд╕рд╛рде рдЗрд╕ рддрд░рд╣ рдХреЗ GC рд╕рд╛рд╡рдзрд╛рди рд╕реВрдЪрдХред рд╕рдм рдХреБрдЫ рдареАрдХ рдФрд░ рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИред
рдПрдХ рдмрд╛рдд рд▓реЗрдХрд┐рди - System.Runtime.CompilerServices.Unsafe рдХреА рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдмрд╛рд╡рдЬреВрдж, Span<T> рдЯрд╛рдЗрдк T рд▓рд┐рдП рдХрд┐рд╕реА рдХреЛ рдирд╣реАрдВ T рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ рд╕реНрдкреИрди рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ 1 + рд▓рдВрдмрд╛рдИ рд╕реВрдЪрдХ рд╣реИ, рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рдЖрдк рдЕрдкрдиреЗ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓рддреЗ рд╣реИрдВ, рдЗрд╕реЗ рдХрд┐рд╕реА рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рд▓рдВрдмрд╛рдИ рдХреЛ рдкреБрдирд░реНрдЧрдгрдирд╛ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдирдпрд╛ рд╕реНрдкреИрди рдмрдирд╛рддреЗ рд╣реИрдВ? рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ public Span<T>(void* pointer, int length) ред
рдЖрдЗрдП рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦреЗрдВ:


 [Test] public void Test() { void Flip(Span<byte> span) {/*   endianess */} Span<int> x = new [] {123}; Span<byte> y = DangerousCast<int, byte>(x); Assert.AreEqual(123, x[0]); Flip(y); Assert.AreNotEqual(123, x[0]); Flip(y); Assert.AreEqual(123, x[0]); } 

рдореЗрд░реЗ рд╕реЗ рдЕрдзрд┐рдХ рдЙрдиреНрдирдд рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рддреБрд░рдВрдд рдорд╣рд╕реВрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдпрд╣рд╛рдВ рдХреНрдпрд╛ рдЧрд▓рдд рд╣реИред рдХреНрдпрд╛ рдкрд░реАрдХреНрд╖рд╛ рдореЗрдВ рдлреЗрд▓ рд╣реЛ рдЬрд╛рдПрдВрдЧреЗ? рдЙрддреНрддрд░, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдорддреМрд░ рдкрд░ рд╣реЛрддрд╛ рд╣реИ, рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ ред
рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рд░рдирдЯрд╛рдЗрдо рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред netframework рдкрд░, рдкрд░реАрдХреНрд╖рдг рдХреЛ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП , рд▓реЗрдХрд┐рди netframework рдкрд░, рдпрд╣ рдХреИрд╕реЗ netframework ред
рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ, рдпрджрд┐ рдЖрдк рдХреБрдЫ рдирд┐рдмрдВрдзреЛрдВ рдХреЛ рд╣рдЯрд╛рддреЗ рд╣реИрдВ, рддреЛ рдкрд░реАрдХреНрд╖рдг 100% рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджреЗрддрд╛ рд╣реИред
рдЪрд▓реЛ рдареАрдХ рд╣реИред


1 рдореИрдВ рдЧрд▓рдд рдерд╛ ред


рд╕рд╣реА рдЙрддреНрддрд░: рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ


рдкрд░рд┐рдгрд╛рдо рдирд┐рд░реНрднрд░ рдХреНрдпреЛрдВ рдХрд░рддрд╛ рд╣реИ?
рдЖрдЗрдП рд╕рднреА рдЕрдирд╛рд╡рд╢реНрдпрдХ рд╣рдЯрд╛ рджреЗрдВ рдФрд░ рдпрд╣рд╛рдВ рдЗрд╕ рддрд░рд╣ рдХрд╛ рдХреЛрдб рд▓рд┐рдЦреЗрдВ:


 private static void Main() => Check(); private static void Check() { Span<int> x = new[] {999, 123, 11, -100}; Span<byte> y = As<int, byte>(ref x); Console.WriteLine(@"FRAMEWORK_NAME"); Write(ref x); Write(ref y); Console.WriteLine(); Write<int, int>(ref x, "Span<int> [0]"); Write<byte, int>(ref y, "Span<byte>[0]"); Console.WriteLine(); Write<int, int>(ref Offset<int, object>(ref x[0], 1), "Span<int> [0] offset by size_t"); Write<byte, int>(ref Offset<byte, object>(ref y[0], 1), "Span<byte>[0] offset by size_t"); Console.WriteLine(); GC.Collect(0, GCCollectionMode.Forced, true, true); Write<int, int>(ref x, "Span<int> [0] after GC"); Write<byte, int>(ref y, "Span<byte>[0] after GC"); Console.WriteLine(); Write(ref x); Write(ref y); } 

Write<T, U> рд╡рд┐рдзрд┐ рдЯрд╛рдЗрдк T рдХреА рдЕрд╡рдзрд┐ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рдкрд╣рд▓реЗ рддрддреНрд╡ рдХрд╛ рдкрддрд╛ рдкрдврд╝рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕ рд╕реВрдЪрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЯрд╛рдЗрдк U рдХрд╛ рдПрдХ рддрддреНрд╡ рдкрдврд╝рддрд╛ рд╣реИред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, Write<int, int>(ref x) рдореЗрдореЛрд░реА рдореЗрдВ рдПрдбреНрд░реЗрд╕ + рдирдВрдмрд░ 999 рдХреЛ рдЖрдЙрдЯрдкреБрдЯ рдХрд░реЗрдЧрд╛ред
рд╕рд╛рдорд╛рдиреНрдп Write рдПрдХ рд╕рд░рдгреА рдкреНрд░рд┐рдВрдЯред
рдЕрдм As<,> рд╡рд┐рдзрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ:


  private static unsafe Span<U> As<T, U>(ref Span<T> span) where T : unmanaged where U : unmanaged { fixed(T* ptr = span) return new Span<U>(ptr, span.Length * Unsafe.SizeOf<T>() / Unsafe.SizeOf<U>()); } 

C# рд╕рд┐рдВрдЯреИрдХреНрд╕ рдЕрдм рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ Span<T>.GetPinnableReference() рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рдЗрд╕ рдирд┐рд╢реНрдЪрд┐рдд-рд░рд╛рдЬреНрдп рд░рд┐рдХреЙрд░реНрдб рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред
рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ x64 рдореЛрдб рдореЗрдВ netframework4.8 рдкрд░ рдЪрд▓рд╛рдПрдБред рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ:


 LEGACY [ 999, 123, 11, -100 ] [ 231, 3, 0, 0, 123, 0, 0, 0, 11, 0, 0, 0, 156, 255, 255, 255 ] 0x|00|00|02|8C|00|00|2F|B0 999 Span<int> [0] 0x|00|00|02|8C|00|00|2F|B0 999 Span<byte>[0] 0x|00|00|02|8C|00|00|2F|B8 11 Span<int> [0] offset by size_t 0x|00|00|02|8C|00|00|2F|B8 11 Span<byte>[0] offset by size_t 0x|00|00|02|8C|00|00|2B|18 999 Span<int> [0] after GC 0x|00|00|02|8C|00|00|2F|B0 6750318 Span<byte>[0] after GC [ 999, 123, 11, -100 ] [ 110, 0, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] 

рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рджреЛрдиреЛрдВ рд╕реНрдкреИрди (рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдмрд╛рд╡рдЬреВрдж) рд╕рдорд╛рди рд░реВрдк рд╕реЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ Span<byte> , рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдореВрд▓ рд╕рд░рдгреА рдХреЗ рдмрд╛рдЗрдЯ-рд╡реНрдпреВ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИред рдЖрдкрдХреЛ рдХреНрдпрд╛ рдЪрд╛рд╣рд┐рдП
рдареАрдХ рд╣реИ, рдЪрд▓реЛ рд╕реНрдкреИрди рдХреА рд╢реБрд░реБрдЖрдд рдХреЛ рдПрдХ IntPtr (рдпрд╛ x64 рдкрд░ 2 X int ) рдХреЗ рдЖрдХрд╛рд░ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ рдФрд░ рдкрдврд╝реЗрдВред рд╣рдореЗрдВ рд╕рд░рдгреА рдХрд╛ рддреАрд╕рд░рд╛ рддрддреНрд╡ рдФрд░ рд╕рд╣реА рдкрддрд╛ рдорд┐рд▓рддрд╛ рд╣реИред рдФрд░ рдлрд┐рд░ рд╣рдо рдХрдЪрд░рд╛ рдЗрдХрдЯреНрдард╛ рдХрд░реЗрдВрдЧреЗ ...


 GC.Collect(0, GCCollectionMode.Forced, true, true); 

рдЗрд╕ рд╡рд┐рдзрд┐ рдореЗрдВ рдЕрдВрддрд┐рдо рдзреНрд╡рдЬ GC рдвреЗрд░ GC рдХреЙрдореНрдкреИрдХреНрдЯ GC рдХрд╣рддрд╛ рд╣реИред GC.Collect рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж GC.Collect GC рдореВрд▓ рд╕реНрдерд╛рдиреАрдп рд╕рд░рдгреА рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред Span<int> рдЗрди рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдорд╛рд░рд╛ Span<byte> рдкреБрд░рд╛рдиреЗ рдкрддреЗ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рдЕрдм рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╣реИред рдПрдХ рдмрд╛рд░ рдореЗрдВ рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдЕрдкрдиреЗ рд╕рднреА рдШреБрдЯрдиреЛрдВ рдХреЛ рд╢реВрдЯ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╢рд╛рдирджрд╛рд░ рддрд░реАрдХрд╛!


рдЕрдм рд╣рдо netcore3.0.100-preview8 рдкрд░ рдХреЙрд▓ рдХрд┐рдП рдЧрдП рд╕рдЯреАрдХ рд╕рдорд╛рди рдХреЛрдб рдЯреБрдХрдбрд╝реЗ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЛ netcore3.0.100-preview8 ред


 CORE [ 999, 123, 11, -100 ] [ 231, 3, 0, 0, 123, 0, 0, 0, 11, 0, 0, 0, 156, 255, 255, 255 ] 0x|00|00|01|F2|8F|BD|C6|90 999 Span<int> [0] 0x|00|00|01|F2|8F|BD|C6|90 999 Span<byte>[0] 0x|00|00|01|F2|8F|BD|C6|98 11 Span<int> [0] offset by size_t 0x|00|00|01|F2|8F|BD|C6|98 11 Span<byte>[0] offset by size_t 0x|00|00|01|F2|8F|BD|BF|38 999 Span<int> [0] after GC 0x|00|00|01|F2|8F|BD|BF|38 999 Span<byte>[0] after GC [ 999, 123, 11, -100 ] [ 231, 3, 0, 0, 123, 0, 0, 0, 11, 0, 0, 0, 156, 255, 255, 255 ] 

рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛрдореИрдВ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реВрдВред рд╕рдВрдШрдирди рдХреЗ рдмрд╛рдж, рджреЛрдиреЛрдВ рд╢реБрдХреНрд░рд╛рдгреБ рдЕрдкрдиреЗ рд╕реВрдЪрдХ рдХреЛ рдмрджрд▓рддреЗ рд╣реИрдВред рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛! рд▓реЗрдХрд┐рди рдЕрдм рдЗрд╕реЗ рдПрдХ рд╡рд┐рд░рд╛рд╕рдд рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдХреИрд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛ рдЬрд╛рдП?


рдЬрд┐рдд рдЖрдВрддрд░рд┐рдХ


рдореИрдВ рдмрд┐рд▓реНрдХреБрд▓ рднреВрд▓ рдЧрдпрд╛ рдХрд┐ рд╕реНрдкреИрди рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдХреЛ рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ netcore рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, netcore рдПрдХ рд╕рд░рдгреА рдХреЗ рдЯреБрдХрдбрд╝реЗ рддрдХ рднреА рдЖрдВрддрд░рд┐рдХ рдкреЙрдЗрдВрдЯрд░реНрд╕ рдмрдирд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ GC рд▓реЗ рдЬрд╛рдиреЗ рдкрд░ рд▓рд┐рдВрдХ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд░ рд╕рдХрддрд╛ рд╣реИред netframework , netframework рдХрд╛ nuget рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдПрдХ рдмреИрд╕рд╛рдЦреА рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рджреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕реНрдкреИрди рд╣реИрдВ: рдПрдХ рдПрд░реЗ рд╕реЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдВрдХ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рддрд╛ рд╣реИ, рджреВрд╕рд░рд╛ рдкреЙрдЗрдВрдЯрд░ рд╕реЗ рдФрд░ рдЗрд╕рдХрд╛ рдХреЛрдИ рдЕрдВрджрд╛рдЬрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕ рдУрд░ рдЗрд╢рд╛рд░рд╛ рдХрд░рддрд╛ рд╣реИред рдореВрд▓ рд╕рд░рдгреА рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╕реНрдкреИрди рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рд╣рддрд╛ рд╣реИ рдХрд┐ рдкреЙрдЗрдВрдЯрд░ рдЕрдкрдиреЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдХрд╣рд╛рдВ рд╕реЗ рдЧреБрдЬрд░рд╛ рд╣реИред рддреБрд▓рдирд╛ рдХреЗ рд▓рд┐рдП, рдпрд╣ netcore рдореЗрдВ рдЕрд╡рдзрд┐ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ:


 readonly ref struct Span<T> where T : unmanaged { private readonly ByReference<T> _pointer; //  -   private readonly int _length; } 

рдФрд░ netframework :


 readonly ref struct Span<T> where T : unmanaged { private readonly Pinnable<T> _pinnable; private readonly IntPtr _byteOffset; private readonly int _length; } 

_pinnable рдореЗрдВ рд╕рд░рдгреА рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрджрд░реНрдн рд╣реЛрддрд╛ рд╣реИ, рдпрджрд┐ рдХрд┐рд╕реА рдХреЛ рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛ рдХреЛ рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, _byteOffset рдореЗрдВ рдПрдХ рдмрджрд▓рд╛рд╡ рд╣реЛрддрд╛ рд╣реИ (рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдкреВрд░реЗ рд╕рд░рдгреА рдореЗрдВ рдХреБрдЫ рдЧреИрд░-рд╢реВрдиреНрдп рдкрд╛рд░реА рд╣реИ рдЬрд┐рд╕ рддрд░рд╣ рд╕реЗ рд╕рд░рдгреА рдХреЛ рдореЗрдореЛрд░реА рдореЗрдВ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╢рд╛рдпрдж )ред рдпрджрд┐ рдЖрдк рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ void* рдкреЙрдЗрдВрдЯрд░ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рдирд┐рд░рдкреЗрдХреНрд╖ _byteOffset рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рд╕реНрдкреИрди рдХреЛ рдореЗрдореЛрд░реА рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рддрдВрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рд╕рднреА рдЙрджрд╛рд╣рд░рдг рд╡рд┐рдзрд┐рдпрд╛рдБ рд╢рд░реНрддреЛрдВ рдХреЗ рд╕рд╛рде рд▓рд╛рдЬрд┐рдореА рд╣реИрдВ рдЬреИрд╕реЗ if(_pinnable is null) {/* */} else {/* _pinnable */} ред рдРрд╕реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдХреНрдпрд╛ рдХрд░реЗрдВ?


рдпрд╣ рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИ рдпрд╣ рдЗрд╕рдХреЗ рд▓рд╛рдпрдХ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЕрднреА рднреА рдХрд┐рдпрд╛ рд╣реИ


рдпрд╣ рдЦрдВрдб netframework рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рд╡рд┐рднрд┐рдиреНрди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдиреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд рд╣реИ, рдЬреЛ Span<T> -> Span<U> рдХреЛ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рд▓рд┐рдВрдХ рд░рдЦрддреЗ рд╣реБрдП netframework рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред
рдореИрдВ рдЖрдкрдХреЛ рдЪреЗрддрд╛рд╡рдиреА рджреЗрддрд╛ рд╣реВрдВ: рдпрд╣ рд╕рдВрднрд╡рддрдГ рдореМрд▓рд┐рдХ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдФрд░ рдЕрдВрдд рдореЗрдВ рдПрдХ рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЗ рд╕рд╛рде рдЕрд╕рд╛рдорд╛рдиреНрдп рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХрд╛ рдПрдХ рдХреНрд╖реЗрддреНрд░ рд╣реИ


рд╡рд┐рдзрд┐ 1: Naive


рдЬреИрд╕рд╛ рдХрд┐ рдЙрджрд╛рд╣рд░рдг рд╕реЗ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ, рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХрд╛ рд░реВрдкрд╛рдВрддрд░рдг netframework рдкрд░ рд╡рд╛рдВрдЫрд┐рдд рдкрд░рд┐рдгрд╛рдо рдирд╣реАрдВ рджреЗрдЧрд╛ред рд╣рдореЗрдВ _pinnable value рдЪрд╛рд╣рд┐рдПред рдареАрдХ рд╣реИ, рд╣рдо рдирд┐рдЬреА рдХреНрд╖реЗрддреНрд░реЛрдВ (рдмрд╣реБрдд рдмреБрд░рд╛ рдФрд░ рд╣рдореЗрд╢рд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ) рдХреЛ рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓рдХрд░ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХреЛ рдЙрдЬрд╛рдЧрд░ рдХрд░реЗрдВрдЧреЗ, рд╣рдо рдЗрд╕реЗ рдПрдХ рдирдИ рд╕реНрдкреИрди рдореЗрдВ рд▓рд┐рдЦреЗрдВрдЧреЗ, рд╣рдо рдЦреБрд╢ рд╣реЛрдВрдЧреЗред рдХреЗрд╡рд▓ рдПрдХ рдЫреЛрдЯреА рд╕реА рд╕рдорд╕реНрдпрд╛ рд╣реИ: рд╕реНрдкреИрди рдПрдХ ref struct , рдпрд╣ рди рддреЛ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рддрд░реНрдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рди рд╣реА рдЗрд╕реЗ рдХрд┐рд╕реА object рдореЗрдВ рдкреИрдХ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХреЗ рдорд╛рдирдХ рддрд░реАрдХреЛрдВ рдХреЛ рд╕реНрдкреИрди рдХреЛ рд╕рдВрджрд░реНрдн рдкреНрд░рдХрд╛рд░ рдореЗрдВ рдзрдХреЗрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдпрд╛ рджреВрд╕рд░реЗ рддрд░реАрдХреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдореБрдЭреЗ рдПрдХ рд╕рд░рд▓ рддрд░реАрдХрд╛ рдирд╣реАрдВ рдорд┐рд▓рд╛ (рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдирд┐рдЬреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдкрд░ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддреЗ рд╣реБрдП)ред


рд╡рд┐рдзрд┐ 2: рд╣рдореЗрдВ рдЧрд╣рд░рд╛рдИ рддрдХ рдЬрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ


рдореЗрд░реЗ ( [1] , [реи] , [рей] ) рд╕реЗ рдкрд╣рд▓реЗ рд╣реА рд╕рдм рдХреБрдЫ рд╣реЛ рдЪреБрдХрд╛ рд╣реИред рд╕реНрдкреЗрди рдПрдХ рд╕рдВрд░рдЪрдирд╛ рд╣реИ, T рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ T рддреАрди рдлрд╝реАрд▓реНрдб рдореЗрдореЛрд░реА рдХреА рд╕рдорд╛рди рдорд╛рддреНрд░рд╛ ( рд╕рдорд╛рди рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдкрд░ ) рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░ рд▓реЗрддреЗ рд╣реИрдВред рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ [FieldOffset(0)] ? рдЬрд▓реНрджреА рд╕реЗ рдирд╣реАрдВ рдХрд╣рд╛ред


 [StructLayout(LayoutKind.Explicit)] ref struct Exchange<T, U> where T : unmanaged where U : unmanaged { [FieldOffset(0)] public Span<T> Span_1; [FieldOffset(0)] public Span<U> Span_2; } 

рд▓реЗрдХрд┐рди рдЬрдм рдЖрдк рдкреНрд░реЛрдЧреНрд░рд╛рдо рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ (рдпрд╛ рдмрд▓реНрдХрд┐, рдЬрдм рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ), рддреЛ TypeLoadException рдорд┐рд▓рддреА TypeLoadException - рдПрдХ рдЬреЗрдиреЗрд░рд┐рдХ LayoutKind.Explicit рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред LayoutKind.Explicit ред рдареАрдХ рд╣реИ, рдХреЛрдИ рдмрд╛рдд рдирд╣реАрдВ, рдЪрд▓реЛ рдореБрд╢реНрдХрд┐рд▓ рд░рд╛рд╕реНрддреЗ рдкрд░ рдЪрд▓рддреЗ рд╣реИрдВ:


 [StructLayout(LayoutKind.Explicit)] public ref struct Exchange { [FieldOffset(0)] public Span<byte> ByteSpan; [FieldOffset(0)] public Span<sbyte> SByteSpan; [FieldOffset(0)] public Span<ushort> UShortSpan; [FieldOffset(0)] public Span<short> ShortSpan; [FieldOffset(0)] public Span<uint> UIntSpan; [FieldOffset(0)] public Span<int> IntSpan; [FieldOffset(0)] public Span<ulong> ULongSpan; [FieldOffset(0)] public Span<long> LongSpan; [FieldOffset(0)] public Span<float> FloatSpan; [FieldOffset(0)] public Span<double> DoubleSpan; [FieldOffset(0)] public Span<char> CharSpan; } 

рдЕрдм рдЖрдк рдпрд╣ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 private static Span<byte> As2(Span<int> span) { var exchange = new Exchange() { IntSpan = span }; return exchange.ByteSpan; } 

рд╡рд┐рдзрд┐ рдХреЗрд╡рд▓ рдПрдХ рд╕рдорд╕реНрдпрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреА рд╣реИ - _length рдХреНрд╖реЗрддреНрд░ _length рдирдХрд▓ рдХреА рдЬрд╛рддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЬрдм int -> byte рдХрд╛рд╕реНрдЯрд┐рдВрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдмрд╛рдЗрдЯ рд╕реНрдкреИрди рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рд░рдгреА рд╕реЗ 4 рдЧреБрдирд╛ рдЫреЛрдЯрд╛ рд╣реЛрддрд╛ рд╣реИред
рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ:


 [StructLayout(LayoutKind.Sequential)] public ref struct Raw { public object Pinnable; public IntPtr Pointer; public int Length; } [StructLayout(LayoutKind.Explicit)] public ref struct Exchange { /* */ [FieldOffset(0)] public Raw RawView; } 

рдЕрдм RawView рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрдк рдкреНрд░рддреНрдпреЗрдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд╕реНрдкреИрди рдлрд╝реАрд▓реНрдб рддрдХ рдкрд╣реБрдВрдЪ рд╕рдХрддреЗ рд╣реИрдВред


 private static Span<byte> As2(Span<int> span) { var exchange = new Exchange() { IntSpan = span }; var exchange2 = new Exchange() { RawView = new Raw() { Pinnable = exchange.RawView.Pinnable, Pointer = exchange.RawView.Pointer, Length = exchange.RawView.Length * sizeof<int> / sizeof<byte> } }; return exchange2.ByteSpan; } 

рдФрд░ рдпрд╣ рд╡реИрд╕реЗ рд╣реА рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЬреИрд╕реЗ рдХрд┐ рдЕрдЧрд░ рдЖрдк рдЧрдВрджреЗ рдЪрд╛рд▓реЛрдВ рдХреЗ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХреЛ рдирдЬрд░рдЕрдВрджрд╛рдЬ рдХрд░рддреЗ рд╣реИрдВред рдорд╛рдЗрдирд╕ - рдХрдирд╡рд░реНрдЯрд░ рдХрд╛ рд╕рд╛рдорд╛рдиреНрдп рд╕рдВрд╕реНрдХрд░рдг рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЖрдкрдХреЛ рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдкреНрд░рдХрд╛рд░реЛрдВ рд╕реЗ рд╕рдВрддреЛрд╖ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред


рд╡рд┐рдзрд┐ 3: рдкрд╛рдЧрд▓


рдХрд┐рд╕реА рднреА рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреА рддрд░рд╣, рдореБрдЭреЗ рдЪреАрдЬреЛрдВ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рдирд╛ рдкрд╕рдВрдж рд╣реИред рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ unmanaged рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдХрдиреНрд╡рд░реНрдЯрд░реНрд╕ рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдиреЗ рдореБрдЭреЗ рдЦреБрд╢ рдирд╣реАрдВ рдХрд┐рдпрд╛ред рдХреНрдпрд╛ рд╕рдорд╛рдзрд╛рди рдкреЗрд╢ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ? рдпрд╣ рд╕рд╣реА рд╣реИ, рдЖрдкрдХреЗ рд▓рд┐рдП рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП CLR рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред


рдЗрд╕реЗ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рдП? рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд░реАрдХреЗ рд╣реИрдВ, рд▓реЗрдЦ рд╣реИрдВ ред рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреА рд╣реИ:
рдПрдХ рдмрд┐рд▓реНрдб рдмрд┐рд▓реНрдбрд░ рдмрдирд╛рдПрдВ -> рдПрдХ рдореЙрдбреНрдпреВрд▓ рдмрд┐рд▓реНрдбрд░ рдмрдирд╛рдПрдВ -> рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдВ -> {рдлреАрд▓реНрдбреНрд╕, рдореЗрдердбреНрд╕, рдЖрджрд┐} -> рдЖрдЙрдЯрдкреБрдЯ рдкрд░ рд╣рдореЗрдВ Type рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдорд┐рд▓рддрд╛ рд╣реИред
рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдкреНрд░рдХрд╛рд░ рдХреНрдпрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП (рдпрд╣ рдПрдХ ref struct ), рд╣рдо ildasm рдкреНрд░рдХрд╛рд░ рдХреЗ рдХрд┐рд╕реА рднреА рдЙрдкрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдбреЙрдЯрдкреЗрдХ рдерд╛ред
рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдмрд┐рд▓реНрдбрд░ рдмрдирд╛рдирд╛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:


 var typeBuilder = _mBuilder.DefineType($"Generated_{typeof(T).Name}", TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.ExplicitLayout // <-    | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit, typeof(ValueType)); 

рдЕрдм рдЦреЗрддред рдЪреВрдБрдХрд┐ рд╣рдо Span<T> рдХреЛ Span<U> рд╕реАрдзреЗ рдХреЙрдкреА рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд▓рдВрдмрд╛рдИ рдореЗрдВ рдЕрдВрддрд░ рдХреЗ рдХрд╛рд░рдг, рд╣рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд╕реНрдЯ рдХреЗ рджреЛ рдкреНрд░рдХрд╛рд░ рдмрдирд╛рдиреЗ рд╣реЛрдВрдЧреЗ


 [StructLayout(LayoutKind.Explicit)] ref struct Generated_Int32 { [FieldOffset(0)] public Span<Int32> Span; [FieldOffset(0)] public Raw Raw; } 

рдпрд╣рд╛рдВ Raw рд╣рдо рдЕрдкрдиреЗ рд╣рд╛рдереЛрдВ рд╕реЗ рдШреЛрд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред IsByRefLikeAttribute рдмрд╛рд░реЗ рдореЗрдВ рдордд рднреВрд▓рдирд╛ред рдЦреЗрддреЛрдВ рдХреЗ рд╕рд╛рде, рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИ:


 var spanField = typeBuilder.DefineField("Span", typeof(Span<T>), FieldAttributes.Private); spanField.SetOffset(0); var rawField = typeBuilder.DefineField("Raw", typeof(Raw), FieldAttributes.Private); rawField.SetOffset(0); 

рдмрд╕ рдЗрддрдирд╛ рд╣реА, рд╕рдмрд╕реЗ рд╕рд░рд▓ рдкреНрд░рдХрд╛рд░ рддреИрдпрд╛рд░ рд╣реИред рдЕрдм рдЕрд╕реЗрдВрдмрд▓реА рдореЙрдбреНрдпреВрд▓ рдХреЛ рдХреИрд╢ рдХрд░реЗрдВред рдХрд╕реНрдЯрдо рдкреНрд░рдХрд╛рд░ рдХреИрд╢реНрдб рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╢рдмреНрджрдХреЛрд╢ рдореЗрдВ ( T -> Generated_{nameof(T)} )ред рд╣рдо рдПрдХ рд░реИрдкрд░ рдмрдирд╛рддреЗ рд╣реИрдВ рдЬреЛ рджреЛ рдкреНрд░рдХрд╛рд░ рдХреЗ TIn рдФрд░ TOut рдЕрдиреБрд╕рд╛рд░ рджреЛ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╣рд╛рдпрдХ рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рд╕реНрдкреИрди рдкрд░ рдЖрд╡рд╢реНрдпрдХ рд╕рдВрдЪрд╛рд▓рди рдХрд░рддрд╛ рд╣реИред рдПрдХ рд╣реИ рд▓реЗрдХрд┐рди рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╕реНрдкреИрди (рдпрд╛ рдЕрдиреНрдп ref struct ) рдкрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд▓рдЧрднрдЧ рдЕрд╕рдВрднрд╡ рд╣реИред рдпрд╛ рдореБрдЭреЗ рдХреЛрдИ рд╕рд░рд▓ рдЙрдкрд╛рдп рдирд╣реАрдВ рдорд┐рд▓рд╛ ред рдХреИрд╕реЗ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ?


рдмрдЪрд╛рд╡ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдирд┐рдзрд┐


рдкрд░рд╛рд╡рд░реНрддрди рд╡рд┐рдзрд┐ рдЖрдорддреМрд░ рдкрд░ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреА рд╣реИ:


  object Invoke(this MethodInfo mi, object @this, object[] otherArgs) 

рд╡реЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдирд╣реАрдВ рд░рдЦрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рдмреЙрдХреНрд╕рд┐рдВрдЧ (= рдкреИрдХреЗрдЬрд┐рдВрдЧ) рдЖрдкрдХреЛ рд╕реНрд╡реАрдХрд╛рд░реНрдп рд╣реИ, рддреЛ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИред
рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, @this рдФрд░ otherArgs рдореЗрдВ рдПрдХ ref struct рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬреЛ рдореБрдЭреЗ рдирд╣реАрдВ рдорд┐рд▓ рд╕рдХрд╛ред
рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рд╕рд░рд▓ рддрд░реАрдХрд╛ рд╣реИред рдЖрдЗрдП рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ рдХрд┐ рдПрдХ рдкреНрд░рдХрд╛рд░ рдореЗрдВ рдЧреЗрдЯреНрдЯрд░ рдФрд░ рд╕реЗрдЯрд░ рд╡рд┐рдзрд┐рдпрд╛рдВ рд╣реИрдВ (рдЧреБрдг рдирд╣реАрдВ, рд▓реЗрдХрд┐рди рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд╕рд░рд▓ рддрд░реАрдХреЗ рдмрдирд╛рдП рдЧрдП рд╣реИрдВ)ред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:


 void Generated_Int32.SetSpan(Span<Int32> span) => this.Span = span; 

рд╡рд┐рдзрд┐ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдПрдХ рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдкреНрд░рдХрд╛рд░ (рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдХреЛрдб рдореЗрдВ) рдХреА рдШреЛрд╖рдгрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 delegate void SpanSetterDelegate<T>(Span<T> span) where T : unmanaged; 

рд╣рдореЗрдВ рдРрд╕рд╛ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рдорд╛рдирдХ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рд▓рд┐рдП рдПрдХ Action<Span<T>> рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рд╕реНрдкреИрди рдХреЛ рдЬреЗрдиреЗрд░рд┐рдХ рддрд░реНрдХреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред SpanSetterDelegate , рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рдмрд┐рд▓реНрдХреБрд▓ рд╡реИрдз рдкреНрд░рддрд┐рдирд┐рдзрд┐ рд╣реИред
рдЖрд╡рд╢реНрдпрдХ рдкреНрд░рддрд┐рдирд┐рдзрд┐рдпреЛрдВ рдХреЛ рдмрдирд╛рдПрдБред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдорд╛рдирдХ рдЬреЛрдбрд╝рддреЛрдбрд╝ рдХрд░реЗрдВ:


 var mi = type.GetMethod("Method_Name"); // ,    public & instance var spanSetter = (SpanSetterDelegate<T>) mi.CreateDelegate(typeof(SpanSetterDelegate<T>), @this); 

рдЕрдм spanSetter рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, spanSetter(Span<T>.Empty); ред @this 2 рдХреЗ рд░реВрдк рдореЗрдВ , рдпрд╣ рд╣рдорд╛рд░реЗ рдЧрддрд┐рд╢реАрд▓ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, Activator.CreateInstance(type) рдорд╛рдзреНрдпрдо рд╕реЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред @this Activator.CreateInstance(type) , рдХреНрдпреЛрдВрдХрд┐ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдХреЛрдИ рддрд░реНрдХ рдХреЗ рд╕рд╛рде рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдирд┐рд░реНрдорд╛рддрд╛ рд╣реИред


рддреЛ, рдЕрдВрддрд┐рдо рд╕реАрдорд╛ - рд╣рдореЗрдВ рд╡рд┐рдзрд┐рдкреВрд░реНрд╡рдХ рд╡рд┐рдзрд┐рдпрд╛рдБ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред


2 рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣рд╛рдВ рдХреБрдЫ рдЧрд▓рдд рд╣реЛ рд░рд╣рд╛ рд╣реИ - Activator.CreateInstance() рдПрдХ ref struct рдЙрджрд╛рд╣рд░рдг Activator.CreateInstance() рдкреИрдХ рдХрд░ рд░рд╣рд╛ рд╣реИред рдЕрдЧрд▓реЗ рднрд╛рдЧ рдХрд╛ рдЕрдВрдд рджреЗрдЦреЗрдВ


Reflection.Emit рдорд┐рд▓реЛ


рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ Expression рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдорд╛рд░реЗ рддреБрдЪреНрдЫ рдкрд╛рдиреЗ рд╡рд╛рд▓реЛрдВ рдХреЗ рд╢рд░реАрд░ / рд╡рд╛рд╕рд┐рдпреЛрдВ рдХрд╛ рд╢рд╛рдмреНрджрд┐рдХ рд░реВрдк рд╕реЗ рдПрдХ-рджреЛ рднрд╛рд╡ рд╣реИрдВред рдореИрдВрдиреЗ рдПрдХ рдЕрд▓рдЧ, рдЕрдзрд┐рдХ рдкреНрд░рддреНрдпрдХреНрд╖ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЪреБрдирд╛ред


рдпрджрд┐ рдЖрдк рдПрдХ рддреБрдЪреНрдЫ рдкрд╛рдиреЗ рд╡рд╛рд▓реЗ рдХреЗ IL- рдХреЛрдб рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдХреБрдЫ рдРрд╕рд╛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ ( Debug , X86 , netframework4.8 )


 nop ldarg.0 ldfld /* - */ stloc.0 br.s /*  */ ldloc.0 ret 

рд░реЛрдХрдиреЗ рдФрд░ рдбреАрдмрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рд╛рд░реЗ рд╕реНрдерд╛рди рд╣реИрдВред
рд░рд┐рд▓реАрдЬрд╝ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ, рдХреЗрд╡рд▓ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЕрд╡рд╢реЗрд╖:


 ldarg.0 ldfld /* - */ ret 

рдЙрджрд╛рд╣рд░рдг рд╡рд┐рдзрд┐ рдХрд╛ рдЕрд╢рдХреНрдд рддрд░реНрдХ рд╣реИ ... this ред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд IL рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ:
1) рдЗрд╕реЗ рдбрд╛рдЙрдирд▓реЛрдб this
2) рдлрд╝реАрд▓реНрдб рдорд╛рди рд▓реЛрдб рдХрд░реЗрдВ
3) рдЗрд╕реЗ рд╡рд╛рдкрд╕ рд▓рд╛рдУ


рдмрд╕ рд╣реБрд╣? Reflection.Emit рдореЗрдВ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдЕрдзрд┐рднрд╛рд░ рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ op рдХреЛрдб рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдПрдХ рдлреАрд▓реНрдб рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдкреИрд░рд╛рдореАрдЯрд░ рднреА рд╣реЛрддрд╛ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рд╣рдордиреЗ рдкрд╣рд▓реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдерд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП spanField ред


 var getSpan = type.DefineMethod("GetSpan", MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.Standard, typeof(Span<T>), Array.Empty<Type>()); gen = getSpan.GetILGenerator(); gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldfld, spanField); gen.Emit(OpCodes.Ret); 

рд╕реЗрдЯрд░ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИ, рдЖрдкрдХреЛ рдЗрд╕реЗ рд╕реНрдЯреИрдХ рдкрд░ рд▓реЛрдб рдХрд░рдиреЗ, рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкрд╣рд▓реЗ рддрд░реНрдХ рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдлрд┐рд░ рдлрд╝реАрд▓реНрдб рдореЗрдВ рд▓реЗрдЦрди рдирд┐рд░реНрджреЗрд╢ рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВ рдФрд░ рдХреБрдЫ рднреА рд╡рд╛рдкрд╕ рди рдХрд░реЗрдВ:


 ldarg.0 ldarg.1 stfld /*   */ ret 

Raw рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрд╡рд╢реНрдпрдХ рдкреНрд░рддрд┐рдирд┐рдзрд┐рдпреЛрдВ (рдпрд╛ рдорд╛рдирдХ рд▓реЛрдЧреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ) рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рддреЗ рд╣реБрдП, рд╣рдореЗрдВ рдПрдХ рдЧрддрд┐рд╢реАрд▓ рдкреНрд░рдХрд╛рд░ рдФрд░ рдЪрд╛рд░ рдПрдХреНрд╕реЗрд╕рд░ рд╡рд┐рдзрд┐рдпрд╛рдВ рдорд┐рд▓рддреА рд╣реИрдВ, рдЬрд┐рдирд╕реЗ рд╕рд╣реА рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдЙрддреНрдкрдиреНрди рд╣реЛрддреЗ рд╣реИрдВред


рд╣рдо рдПрдХ рд░реИрдкрд░ рдХреНрд▓рд╛рд╕ рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдЬреЛ рджреЛ рдЬреЗрдиреЗрд░рд┐рдХ рдорд╛рдкрджрдВрдбреЛрдВ ( TIn , TOut ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП Type рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╕рдВрдмрдВрдзрд┐рдд (рдХреИрд╢реНрдб) рдбрд╛рдпрдирд╛рдорд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдпрд╣ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдПрдХ рд╡рд╕реНрддреБ рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдЪрд╛рд░ рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рддрд┐рдирд┐рдзрд┐рдпреЛрдВ рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рддреН


  1. void SetSpan(Span<TIn> span) рд╕рдВрд░рдЪрдирд╛ рдХреЛ рд╕реНрд░реЛрдд рд╕реНрдкреИрди рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП
  2. Raw GetRaw() рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╕реНрдкреИрди рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП Raw GetRaw()
  3. void SetRaw(Raw raw) рд╕рдВрд╢реЛрдзрд┐рдд Raw рд╕рдВрд░рдЪрдирд╛ рдХреЛ рджреВрд╕рд░реА рд╡рд╕реНрддреБ рдореЗрдВ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП
  4. Span<TOut> GetSpan() рд╡рд╛рдВрдЫрд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕реНрдкреИрди рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд╕реЗрдЯ рдФрд░ рдкреБрдирд░реНрдЧрдард┐рдд рдлрд╝реАрд▓реНрдб рдХреЗ рд╕рд╛рде рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред

рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ, рдЧрддрд┐рд╢реАрд▓ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рдПрдХ рдмрд╛рд░ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдПрдХ рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдмрдирд╛рддреЗ рд╕рдордп, рдЗрди рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдПрдХ рд╕рдВрджрд░реНрдн @this рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣рд╛рдВ рдирд┐рдпрдореЛрдВ рдХрд╛ рдЙрд▓реНрд▓рдВрдШрди рд╣реИред Activator.CreateInstance рд░рд┐рдЯрд░реНрди object ред рдЬрд╛рд╣рд┐рд░рд╛ рддреМрд░ рдкрд░ рдпрд╣ рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдЧрддрд┐рд╢реАрд▓ рдкреНрд░рдХрд╛рд░ рдиреЗ рдЦреБрдж рдХреЛ type.IsByRef рдЬреИрд╕рд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдерд╛ ( type.IsByRef Like == false ), рд▓реЗрдХрд┐рди рдпрд╣ ref -рд╕рдорд╛рди рдлрд╝реАрд▓реНрдб рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрднрд╡ рдерд╛ред рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдЗрд╕ рддрд░рд╣ рдХрд╛ рдкреНрд░рддрд┐рдмрдВрдз рднрд╛рд╖рд╛ рдореЗрдВ рдореМрдЬреВрдж рд╣реИ, рд▓реЗрдХрд┐рди CLR рдЗрд╕реЗ рдкрдЪрд╛рддрд╛ рд╣реИред рд╢рд╛рдпрдж рдпрд╣ рдпрд╣рд╛рдВ рд╣реИ рдХрд┐ рдЧреИрд░-рдорд╛рдирдХ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдШреБрдЯрдиреЛрдВ рдХреЛ рдЧреЛрд▓реА рдорд╛рд░ рджреА рдЬрд╛рдПрдЧреАред 3


рддреЛ, рд╣рдореЗрдВ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдорд┐рд▓рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЪрд╛рд░ рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдФрд░ рдЧрддрд┐рд╢реАрд▓ рд╡рд░реНрдЧреЛрдВ рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рджреЛ рдирд┐рд╣рд┐рдд рд╕рдВрджрд░реНрдн рд╣реЛрддреЗ рд╣реИрдВред рдПрдХ рд╣реА рдЬрд╛рддрд┐ рдХреЛ рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рд░рдЦрддреЗ рд╕рдордп рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдФрд░ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдлрд┐рд░ рд╕реЗ рдПрдХ рдЬреЛрдбрд╝реА (TIn, TOut) -> Generator<TIn, TOut> рд▓рд┐рдП рдХреИрд╢ (рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдХрдирд╡рд░реНрдЯрд░ (TIn, TOut) -> Generator<TIn, TOut> ред


рд╕реНрдЯреНрд░реЛрдХ рдЕрдВрддрд┐рдо рд╣реИ: рд╣рдо рдкреНрд░рдХрд╛рд░ рджреЗрддреЗ рд╣реИрдВ, Span<TIn> -> Span<TOut>


 public Span<TOut> Cast(Span<TIn> span) { //      if (span.IsEmpty) return Span<TOut>.Empty; // Caller   ,       if (span.Length * Unsafe.SizeOf<TIn>() % Unsafe.SizeOf<TOut>() != 0) throw new InvalidOperationException(); //      // Span<TIn> _input.Span = span; _spanSetter(span); //  Raw // Raw raw = _input.Raw; var raw = _rawGetter(); var newRaw = new Raw() { Pinnable = raw.Pinnable, //    Pinnable Pointer = raw.Pointer, //   Length = raw.Length * Unsafe.SizeOf<TIn>() / Unsafe.SizeOf<TOut>() //   }; //   Raw    // Raw _output.Raw = newRaw; _rawSetter(newRaw); //     // Span<TOut> _output.Span return _spanGetter(); } 

рдирд┐рд╖реНрдХрд░реНрд╖


рдХрднреА-рдХрднреА рдЦреЗрд▓ рдХреЗ рд╣рд┐рдд рдХреЗ рд▓рд┐рдП - рдЖрдк рднрд╛рд╖рд╛ рдХреА рдХреБрдЫ рд╕реАрдорд╛рдУрдВ рдХреЛ рджрд░рдХрд┐рдирд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЧреИрд░-рдорд╛рдирдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдмреЗрд╢рдХ, рдЕрдкрдиреЗ рдЬреЛрдЦрд┐рдо рдФрд░ рдЬреЛрдЦрд┐рдо рдкрд░ред рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдЧрддрд┐рд╢реАрд▓ рд╡рд┐рдзрд┐ рдЖрдкрдХреЛ рдкреЙрдЗрдВрдЯрд░реНрд╕ рдФрд░ unsafe / fixed рд╕рдВрджрд░реНрднреЛрдВ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рддреНрдпрд╛рдЧрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ, рдЬреЛ рдПрдХ рдмреЛрдирд╕ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рд╕реНрдкрд╖реНрдЯ рдирдХрд╛рд░рд╛рддреНрдордХ рдкрдХреНрд╖ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдФрд░ рдкреНрд░рдХрд╛рд░ рдХреА рдкреАрдврд╝реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред


рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЕрдВрдд рддрдХ рдкрдврд╝реЗ рд╣реИрдВред


Naive рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдкрд░рд┐рдгрд╛рдо

рдФрд░ рдпрд╣ рд╕рдм рдХрд┐рддрдиреА рдЬрд▓реНрджреА рд╣реИ?
рдореИрдВрдиреЗ рдПрдХ рдмреЗрд╡рдХреВрдл рдкрд░рд┐рджреГрд╢реНрдп рдореЗрдВ рдЬрд╛рддрд┐рдпреЛрдВ рдХреА рдЧрддрд┐ рдХреА рддреБрд▓рдирд╛ рдХреА, рдЬреЛ рдРрд╕реА рдЬрд╛рддрд┐рдпреЛрдВ рдФрд░ рдлреИрд▓рд╛рд╡реЛрдВ рдХреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ / рд╕рдВрднрд╛рд╡рд┐рдд рдЙрдкрдпреЛрдЧ рдХреЛ рдирд╣реАрдВ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрдо рд╕реЗ рдХрдо рдЧрддрд┐ рдХрд╛ рдПрдХ рд╡рд┐рдЪрд╛рд░ рджреЗрддрд╛ рд╣реИред


  1. Cast_Explicitрд╡рд┐рдзрд┐ 2 рдХреЗ рдЕрдиреБрд╕рд╛рд░ , рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдШреЛрд╖рд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд░реВрдкрд╛рдВрддрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ ред рдкреНрд░рддреНрдпреЗрдХ рдЬрд╛рддрд┐ рдХреЛ рджреЛ рдЫреЛрдЯреА рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рдЖрд╡рдВрдЯрди рдФрд░ рдЦреЗрддреЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ;
  2. Cast_ILрд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ 3 , рд▓реЗрдХрд┐рди рд╣рд░ рдмрд╛рд░ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рддрд╛ рд╣реИ Generator<TIn, TOut>, рдЬреЛ рд╢рдмреНрджрдХреЛрд╢реЛрдВ рдореЗрдВ рдирд┐рд░рдВрддрд░ рдЦреЛрдЬреЛрдВ рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ, рдкрд╣рд▓реА рдкрд╛рд╕ рдХреЗ рдмрд╛рдж рд╕рднреА рдкреНрд░рдХрд╛рд░ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ;
  3. Cast_IL_Cachedрд╕реАрдзреЗ рдХрдирд╡рд░реНрдЯрд░ рдЙрджрд╛рд╣рд░рдг рдХреЛ рдХреИрд╢ рдХрд░рддрд╛ рд╣реИ Generator<TIn, TOut>, рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдпрд╣ рдФрд╕рдд рдкрд░ рддреЗрдЬреА рд╕реЗ рдирд┐рдХрд▓рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдкреВрд░реА рдЬрд╛рддрд┐ рдЪрд╛рд░ рдкреНрд░рддрд┐рдирд┐рдзрд┐рдпреЛрдВ рдХреА рдХреЙрд▓ рдХреЗ рд▓рд┐рдП рдЙрдмрд▓рддреА рд╣реИ;
  4. Buffer , , . .

тАФ int[N] N/2 .


, , . , . , , . , unmanaged .


 BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362 Intel Core i7-2700K CPU 3.50GHz (Sandy Bridge), 1 CPU, 8 logical and 4 physical cores [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.8.3815.0 Clr : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.8.3815.0 Job=Clr Runtime=Clr InvocationCount=1 UnrollFactor=1 

MethodNMeanErrorStdDevMedianRatioRatioSD
Cast_Explicit100362.2 ns18.0967 ns52.7888 ns400.0 ns1.000.00
Cast_IL1001,237.9 ns28.5954 ns67.4027 ns1,200.0 ns3.470.51
Cast_IL_Cached100522.8 ns25.2640 ns71.2576 ns500.0 ns1.460.27
Buffer100300.0 ns0.0000 ns0.0000 ns300.0 ns0.780.11
Cast_Explicit10002,628.6 ns54.0688 ns64.3650 ns2,600.0 ns1.000.00
Cast_IL10003,216.7 ns49.8568 ns38.9249 ns3,200.0 ns1.210.03
Cast_IL_Cached10002,484.6 ns44.9717 ns37.5534 ns2,500.0 ns0.940.02
Buffer10002,055.6 ns43.9695 ns73.4631 ns2,000.0 ns0.780.03
Cast_Explicit10000002,515,157.1 ns11,809.8538 ns10,469.1278 ns2,516,050.0 ns1.000.00
Cast_IL10000002,263,826.7 ns23,724.4930 ns22,191.9054 ns2,262,000.0 ns0.900.01
Cast_IL_Cached10000002,265,186.7 ns19,505.5913 ns18,245.5422 ns2,266,300.0 ns0.900.01
Buffer10000001,959,547.8 ns39,175.7435 ns49,544.7719 ns1,959,200.0 ns0.780.02
Cast_Explicit100000000255,751,392.9 ns2,595,107.7066 ns2,300,495.3873 ns255,298,950.0 ns1.000.00
Cast_IL100000000228,709,457.1 ns527,430.9293 ns467,553.7809 ns228,864,100.0 ns0.890.01
Cast_IL_Cached100000000227,966,553.8 ns355,027.3545 ns296,463.9203 ns227,903,600.0 ns0.890.01
Buffer100000000213,216,776.9 ns1,198,565.1142 ns1,000,856.1536 ns213,517,800.0 ns0.830.01

Acknowledgements

JetBrains ( :-)) R# VS standalone- dotPeek , . BenchmarkDotNet BenchmarkDotNet, youtube- NDC Conferences DotNext , , .


рдкреБрдирд╢реНрдЪ


3 , ref , , . ( ) . ref structs,


 static Raw Generated_Int32.GetRaw(Span<int> span) { var inst = new Generated_Int32() { Span = span }; return inst.Raw; } 

, Reflection.Emit . , ILGenerator.DeclareLocal .


 static Span<int> Generated_Int32.GetSpan(Raw raw); 


 delegate Raw GetRaw<T>(Span<T> span) where T : unmanaged; delegate Span<T> GetSpan<T>(Raw raw) where T : unmanaged; 

, , ref тАФ . рдХреНрдпреЛрдВрдХрд┐ ,


 var getter = type.GetMethod(@"GetRaw", BindingFlags.Static | BindingFlags.Public).CreateDelegate(typeof(GetRaw<T>), null) as GetRaw<T>; 

тАФ


 Raw raw = getter(Span<TIn>.Empty); Raw newRaw = convert(raw); Span<TOut> = setter(newRaw); 

UPD01:

Source: https://habr.com/ru/post/hi465077/


All Articles