
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[]
рдПрдХ рдЕрд╕рдореНрдкреАрдбрд┐рдд рд╕рд░рдгреА рдХреЛ рд▓рд┐рдЦрдиреЗ (рдпрд╛ рдкрдврд╝рдиреЗ) рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреА рд╕рдорд╛рдкреНрддрд┐ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рддреБрдЪреНрдЫ рдХрд╛рд░реНрдпред
рдХреБрдЫ рд╕реНрдкрд╖реНрдЯ рд╕рдорд╛рдзрд╛рди рдХреНрдпрд╛ рд╣реИрдВ?
- рд╣рдо рд╕рд░рдгреА
T[]
рдкрд░ рдкреБрдирд░рд╛рд╡реГрддрд┐ рдХрд░рддреЗ рд╣реИрдВ, BitConverter.GetBytes(T)
рдХреЙрд▓ рдХрд░реЗрдВ, рдЗрди рдХреБрдЫ рдмрд╛рдЗрдЯреНрд╕ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░реЗрдВ, рд▓рдХреНрд╖реНрдп рд╕рд░рдгреА рдореЗрдВ рдХреЙрдкреА рдХрд░реЗрдВред - рд╣рдо рд╕рд░рдгреА
T[]
рдкрд░ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд░рддреЗ рд╣реИрдВ, new byte[] {(byte)((x & 0xFF00) >> 8), (byte)(x & 0x00FF)};
(рдбрдмрд▓-рдмрд╛рдЗрдЯ рдкреНрд░рдХрд╛рд░ рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП), рд▓рдХреНрд╖реНрдп рд╕рд░рдгреА рдкрд░ рд▓рд┐рдЦреЗрдВред - * рд▓реЗрдХрд┐рди
T[]
рдПрдХ рд╕рд░рдгреА рд╣реИ? рддрддреНрд╡ рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рд╣реИрдВ, рд╣реИ рдирд╛? рддреЛ рдЖрдк рд╕рднреА рддрд░рд╣ рд╕реЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, Buffer.BlockCopy(intArray, 0, byteArray, 0, intArray.Length * sizeof(int));
ред рд╡рд┐рдзрд┐ рд╕рд░рдгреА рдХреЛ рдЪреЗрдХрд┐рдВрдЧ рдкреНрд░рдХрд╛рд░ рдХреА рдЕрдирджреЗрдЦреА рдХрд░ рд╕рд░рдгреА рдХреЛ рдХреЙрдкреА рдХрд░рддреА рд╣реИред рдпрд╣ рдХреЗрд╡рд▓ рд╕реАрдорд╛рдУрдВ рдФрд░ рдЖрд╡рдВрдЯрди рдХреЛ рдпрд╛рдж рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИред рд╣рдо рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдмрд╛рдЗрдЯреНрд╕ рдХреЛ рдорд┐рд▓рд╛рддреЗ рд╣реИрдВред - * рд╡реЗ рдХрд╣рддреЗ рд╣реИрдВ рдХрд┐
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) {} 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;
рдФрд░ 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
рдЕрдм рдЦреЗрддред рдЪреВрдБрдХрд┐ рд╣рдо 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");
рдЕрдм 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
рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╕рдВрдмрдВрдзрд┐рдд (рдХреИрд╢реНрдб) рдбрд╛рдпрдирд╛рдорд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдпрд╣ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдПрдХ рд╡рд╕реНрддреБ рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдЪрд╛рд░ рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рддрд┐рдирд┐рдзрд┐рдпреЛрдВ рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рддреН
void SetSpan(Span<TIn> span)
рд╕рдВрд░рдЪрдирд╛ рдХреЛ рд╕реНрд░реЛрдд рд╕реНрдкреИрди рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдПRaw GetRaw()
рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╕реНрдкреИрди рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП Raw GetRaw()
void SetRaw(Raw raw)
рд╕рдВрд╢реЛрдзрд┐рдд Raw
рд╕рдВрд░рдЪрдирд╛ рдХреЛ рджреВрд╕рд░реА рд╡рд╕реНрддреБ рдореЗрдВ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП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) {
рдирд┐рд╖реНрдХрд░реНрд╖
рдХрднреА-рдХрднреА рдЦреЗрд▓ рдХреЗ рд╣рд┐рдд рдХреЗ рд▓рд┐рдП - рдЖрдк рднрд╛рд╖рд╛ рдХреА рдХреБрдЫ рд╕реАрдорд╛рдУрдВ рдХреЛ рджрд░рдХрд┐рдирд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЧреИрд░-рдорд╛рдирдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдмреЗрд╢рдХ, рдЕрдкрдиреЗ рдЬреЛрдЦрд┐рдо рдФрд░ рдЬреЛрдЦрд┐рдо рдкрд░ред рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдЧрддрд┐рд╢реАрд▓ рд╡рд┐рдзрд┐ рдЖрдкрдХреЛ рдкреЙрдЗрдВрдЯрд░реНрд╕ рдФрд░ unsafe / fixed
рд╕рдВрджрд░реНрднреЛрдВ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рддреНрдпрд╛рдЧрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ, рдЬреЛ рдПрдХ рдмреЛрдирд╕ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рд╕реНрдкрд╖реНрдЯ рдирдХрд╛рд░рд╛рддреНрдордХ рдкрдХреНрд╖ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдФрд░ рдкреНрд░рдХрд╛рд░ рдХреА рдкреАрдврд╝реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЕрдВрдд рддрдХ рдкрдврд╝реЗ рд╣реИрдВред
Naive рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдкрд░рд┐рдгрд╛рдордФрд░ рдпрд╣ рд╕рдм рдХрд┐рддрдиреА рдЬрд▓реНрджреА рд╣реИ?
рдореИрдВрдиреЗ рдПрдХ рдмреЗрд╡рдХреВрдл рдкрд░рд┐рджреГрд╢реНрдп рдореЗрдВ рдЬрд╛рддрд┐рдпреЛрдВ рдХреА рдЧрддрд┐ рдХреА рддреБрд▓рдирд╛ рдХреА, рдЬреЛ рдРрд╕реА рдЬрд╛рддрд┐рдпреЛрдВ рдФрд░ рдлреИрд▓рд╛рд╡реЛрдВ рдХреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ / рд╕рдВрднрд╛рд╡рд┐рдд рдЙрдкрдпреЛрдЧ рдХреЛ рдирд╣реАрдВ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрдо рд╕реЗ рдХрдо рдЧрддрд┐ рдХрд╛ рдПрдХ рд╡рд┐рдЪрд╛рд░ рджреЗрддрд╛ рд╣реИред
Cast_Explicit
рд╡рд┐рдзрд┐ 2 рдХреЗ рдЕрдиреБрд╕рд╛рд░ , рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдШреЛрд╖рд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд░реВрдкрд╛рдВрддрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ ред рдкреНрд░рддреНрдпреЗрдХ рдЬрд╛рддрд┐ рдХреЛ рджреЛ рдЫреЛрдЯреА рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рдЖрд╡рдВрдЯрди рдФрд░ рдЦреЗрддреЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ;Cast_IL
рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ 3 , рд▓реЗрдХрд┐рди рд╣рд░ рдмрд╛рд░ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рддрд╛ рд╣реИ Generator<TIn, TOut>
, рдЬреЛ рд╢рдмреНрджрдХреЛрд╢реЛрдВ рдореЗрдВ рдирд┐рд░рдВрддрд░ рдЦреЛрдЬреЛрдВ рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ, рдкрд╣рд▓реА рдкрд╛рд╕ рдХреЗ рдмрд╛рдж рд╕рднреА рдкреНрд░рдХрд╛рд░ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ;Cast_IL_Cached
рд╕реАрдзреЗ рдХрдирд╡рд░реНрдЯрд░ рдЙрджрд╛рд╣рд░рдг рдХреЛ рдХреИрд╢ рдХрд░рддрд╛ рд╣реИ Generator<TIn, TOut>
, рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдпрд╣ рдФрд╕рдд рдкрд░ рддреЗрдЬреА рд╕реЗ рдирд┐рдХрд▓рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдкреВрд░реА рдЬрд╛рддрд┐ рдЪрд╛рд░ рдкреНрд░рддрд┐рдирд┐рдзрд┐рдпреЛрдВ рдХреА рдХреЙрд▓ рдХреЗ рд▓рд┐рдП рдЙрдмрд▓рддреА рд╣реИ;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
рдкреБрдирд╢реНрдЪ
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: