Guide
Target frameworks
What differs between the .NET 10, .NET Standard and .NET Framework 4.7 builds.
| Target | Used by | Scanner |
|---|---|---|
net10.0 |
.NET 10 and later | SIMD: AVX-512, AVX2 or 128-bit vectors (SSE, NEON), chosen at startup |
net8.0 |
.NET 8 and 9 | as net10.0, without the AVX-512 VBMI2 compress of the index, whose intrinsics came with .NET 10 |
net47 |
.NET Framework 4.7 and later | 64-bit integers: the masks of each 64-byte block from eight ulongs, then the same pipeline |
netstandard2.1 |
.NET Core 3.0 to .NET 7, Mono, Unity 2021.2 and later | same as net47 |
netstandard2.0 |
everything else: .NET Core 2.x, Unity before 2021.2 | same as net47 |
net47 and netstandard2.0 depend on two Microsoft packages, System.Memory and Microsoft.Bcl.AsyncInterfaces;
netstandard2.1, which has spans and async streams built in, only on System.Runtime.CompilerServices.Unsafe. Every
build reads and writes exactly the same CSV: the tests run on .NET 10, on .NET 8 and on .NET Framework 4.8 (the net47
build, whose code the netstandard2.0 and netstandard2.1 builds share), and on .NET 10 the 64-bit scanner is also
checked against the SIMD ones. The differences between the .NET builds (net10.0 and net8.0) and the others:
- Parsing to a type.
Parse<T>,TryParse<T>,ParseOrNull<T>andParseExact<T>parse the built-in types (int,long,short,byte,sbyte,ushort,uint,ulong,double,float,decimal,bool,char,DateTime,DateTimeOffset,TimeSpan,Guid,BigInteger,IPAddress,stringand enums) on every target. Any otherISpanParsable<T>type (DateOnly,Half, your own types) needs generic math, so only the .NET builds parse it; the other builds throwNotSupportedException. Enums are notISpanParsable<T>: on the .NET builds their overloads are the extension methods ofCsvEnumExtensions, so the calls are the same everywhere. On every target,Parse(index, parser),TryParse(index, parser, out value)andCsvField.ParseOrNull(parser)take a parser that gets the field as a string and the reader's format provider:reader.Parse(3, (text, _) => Version.Parse(text)).[CsvRecord]members follow the same rule. - Writing values.
WriteField<T>takesIUtf8SpanFormattablevalues on .NET andIFormattablevalues elsewhere (numbers in the invariant culture are still formatted straight to UTF-8). TheDateOnly,HalfandInt128overloads are .NET only. On the older targetsWriteRecordandWriteHeaderalso take arrays, for compilers before C# 13. - Floating point. Doubles and floats are written in the shortest form that round-trips, as .NET Core 3.0 and
later write them, not as .NET Framework's 15-digit
ToString(). Parsing is exactly rounded, except for inputs the fast parser leaves to the BCL (thousands separators, other cultures, more than 19 significant digits right on a rounding boundary): .NET Framework'sdouble.Parseis not always exactly rounded. - C# version. The options are records with
initproperties: setting them needs C# 9 or later in the calling project (<LangVersion>latest</LangVersion>works for .NET Framework projects too). - Speed. Without SIMD, and with the slower spans of the
System.Memorypackage, expect about a quarter of the .NET 10 speed. On an Intel Core i7-12800H, reading 52 MB of the PackageAssets data as strings took 89 ms on .NET Framework 4.8 x64 (23 ms on .NET 10). Scanning alone ran at 1.5 GB/s (7.2 GB/s on .NET 10),ParallelEnumerateat 1.2 GB/s.
Trimming and native AOT
The net10.0 and net8.0 builds of CsvHelper and CsvHelper.Linq are marked IsAotCompatible and IsTrimmable, so the trimming
and AOT analyzers check them on every build. Reading, writing and [CsvRecord] types work in trimmed and native AOT
applications: the generated mappers are registered by a module initializer, not found with reflection. Two things need
code generated at run time:
- C#'s
dynamic, which needs the runtime binder (Microsoft.CSharp);GetRecords<CsvDynamicRecord>()reads the same records without it (Dynamic records). - The queries of CsvHelper.Linq (
CsvQueryable,CsvQuery<T>,CsvTable<T>), which carry[RequiresDynamicCode]and[RequiresUnreferencedCode]so applications get warnings where they use them.WriteCsvandAppendCsvare safe.