Migration guide
Migrating to v13.0.0
Moving to v13.0.0 from v12.3.2. Changelog.
CsvHelper 13 makes you choose the culture. Without a configuration, the reader, writer, parser and serializer used the
machine's current culture; now their constructors require a CultureInfo, and so does the configuration, which is
renamed CsvConfiguration. The culture reads and writes numbers and dates, and gives the default delimiter. 13 also
adds GetRecordsAsync and WriteRecordsAsync, a choice of line endings, mapping attributes of your own, and a
.NET Standard 2.1 build next to .NET Standard 2.0 and .NET Framework 4.5 and 4.7.
Creating a reader or writer
Pass the culture as the second argument:
using var csv = new CsvReader(reader);using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);Which culture? 12 used CultureInfo.CurrentCulture, both for values and for the delimiter, which was the culture's
list separator (; in many European cultures). Pass CultureInfo.CurrentCulture to keep that, or
CultureInfo.InvariantCulture (, between fields, . in numbers) for files that shouldn't depend on the settings
of the machine that reads or writes them.
| Before | After | Notes |
|---|---|---|
new CsvReader(textReader) |
new CsvReader(textReader, culture) |
|
new CsvReader(textReader, leaveOpen) |
new CsvReader(textReader, culture, leaveOpen) |
|
new CsvWriter(textWriter) |
new CsvWriter(textWriter, culture) |
The culture also chooses the line ending: see Behavior changes. |
new CsvWriter(textWriter, leaveOpen) |
new CsvWriter(textWriter, culture, leaveOpen) |
|
new CsvParser(...), new CsvSerializer(...) |
The same, with the culture second | |
factory.CreateParser(textReader), CreateReader, CreateWriter |
factory.CreateParser(textReader, culture), and so on |
Also on IFactory. |
Configuration
Configuration is renamed CsvConfiguration, so that the class no longer has the name of its namespace,
CsvHelper.Configuration. It has no parameterless constructor: pass the culture.
var config = new CsvHelper.Configuration.Configuration
{
Delimiter = ";",
HasHeaderRecord = false,
};
using var csv = new CsvReader(reader, config);var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
Delimiter = ";",
HasHeaderRecord = false,
};
using var csv = new CsvReader(reader, config);The constructor sets Delimiter to the culture's list separator, as new Configuration(culture) did in 12. Every
other place that took a Configuration takes a CsvConfiguration: the reader and writer constructors,
ReadingContext, WritingContext, ClassMapCollection, IFactory, and the protected AutoMapMembers and
AutoMapConstructorParameters of ClassMap.
Class maps
AutoMap() takes the culture, or a configuration:
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
public class FooMap : ClassMap<Foo>
{
public FooMap()
{
AutoMap();
Map(m => m.Name).Name("Foo Name");
}
}public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
public class FooMap : ClassMap<Foo>
{
public FooMap()
{
AutoMap(CultureInfo.InvariantCulture);
Map(m => m.Name).Name("Foo Name");
}
}AutoMap(culture) auto maps with a new CsvConfiguration for that culture. When your configuration changes how
members are found, such as MemberTypes or IncludePrivateMembers, pass it instead: AutoMap(config).
Mapping attributes
The mapping attributes are applied through two interfaces, IMemberMapper and IMemberReferenceMapper, instead of
a fixed list of attributes. Each one configures the MemberMap (or MemberReferenceMap) of the member it is on, so
an attribute of your own can configure a member the way a class map does:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class YesNoAttribute : Attribute, IMemberMapper
{
public void ApplyTo(MemberMap memberMap)
{
memberMap.Data.TypeConverterOptions.BooleanTrueValues.Add("yes");
memberMap.Data.TypeConverterOptions.BooleanFalseValues.Add("no");
}
}
public class Foo
{
[YesNo]
public bool IsActive { get; set; }
}
Attributes are read when a type is auto mapped, the built-in ones as before.
Async records
GetRecordsAsync<T>() reads records as an IAsyncEnumerable<T>, and WriteRecordsAsync writes them with
asynchronous calls:
public class Foo
{
public int Id { get; set; }
}
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
await foreach (var foo in csv.GetRecordsAsync<Foo>())
{
// ...
}
}
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
await csv.WriteRecordsAsync(new List<Foo> { new Foo { Id = 1 } });
}
- Frameworks:
GetRecordsAsync, its overloads andEnumerateRecordsAsyncare in the .NET Standard and .NET Framework 4.7 builds, not in the .NET Framework 4.5 build. On .NET Standard 2.0 and .NET Framework 4.7,IAsyncEnumerable<T>comes from the Microsoft.Bcl.AsyncInterfaces package, a new dependency. - Your own
IReaderorIWriter: the interfaces have the new methods, so an implementation needs them too.
Behavior changes
The writer ended records with \r\n in 12 (since 12.1.3). In 13 the line ending is the new NewLine setting, and
its default depends on the culture of the configuration: \r\n for CultureInfo.InvariantCulture, and
Environment.NewLine for any other culture, which is \n on Linux and macOS. To write \r\n with another culture,
set it:
var config = new CsvConfiguration(CultureInfo.CurrentCulture)
{
NewLine = NewLine.CRLF,
};
using var csv = new CsvWriter(writer, config);
NewLine is CRLF, CR, LF or Environment.
All API changes
Every change to the public API since v12.3.2: 47 added, 41 changed, 13 removed (38 breaking). New target framework: netstandard2.1. Open a type to see its changes.
CsvHelper
CsvFieldReaderclass2 breaking2 changed
CsvFieldReader(TextReader, CsvConfiguration)Breaking
The parameters changed from (TextReader, Configuration) to (TextReader, CsvConfiguration).
public CsvFieldReader(TextReader reader, Configuration configuration)public CsvFieldReader(TextReader reader, CsvConfiguration configuration)CsvFieldReader(TextReader, CsvConfiguration, bool)Breaking
The parameters changed from (TextReader, Configuration, bool) to (TextReader, CsvConfiguration, bool).
public CsvFieldReader(TextReader reader, Configuration configuration, bool leaveOpen)public CsvFieldReader(TextReader reader, CsvConfiguration configuration, bool leaveOpen)CsvParserclass4 breaking1 removed3 changed1 added
CsvParser(TextReader, CsvConfiguration)Breaking
The parameters changed from (TextReader, Configuration) to (TextReader, CsvConfiguration).
public CsvParser(TextReader reader, Configuration configuration)public CsvParser(TextReader reader, CsvConfiguration configuration)CsvParser(TextReader, CsvConfiguration, bool)Breaking
The parameters changed from (TextReader, Configuration, bool) to (TextReader, CsvConfiguration, bool).
public CsvParser(TextReader reader, Configuration configuration, bool leaveOpen)public CsvParser(TextReader reader, CsvConfiguration configuration, bool leaveOpen)CsvParser(TextReader, CultureInfo)Breaking
The parameters changed from (TextReader, bool) to (TextReader, CultureInfo).
public CsvParser(TextReader reader, bool leaveOpen)public CsvParser(TextReader reader, CultureInfo culture)Removed
Added
CsvReaderclass4 breaking1 removed3 changed5 added
CsvReader(TextReader, CsvConfiguration)Breaking
The parameters changed from (TextReader, Configuration) to (TextReader, CsvConfiguration).
public CsvReader(TextReader reader, Configuration configuration)public CsvReader(TextReader reader, CsvConfiguration configuration)CsvReader(TextReader, CsvConfiguration, bool)Breaking
The parameters changed from (TextReader, Configuration, bool) to (TextReader, CsvConfiguration, bool).
public CsvReader(TextReader reader, Configuration configuration, bool leaveOpen)public CsvReader(TextReader reader, CsvConfiguration configuration, bool leaveOpen)CsvReader(TextReader, CultureInfo)Breaking
The parameters changed from (TextReader, bool) to (TextReader, CultureInfo).
public CsvReader(TextReader reader, bool leaveOpen)public CsvReader(TextReader reader, CultureInfo culture)Removed
Added
CsvSerializerclass4 breaking1 removed3 changed1 added
CsvSerializer(TextWriter, CsvConfiguration)Breaking
The parameters changed from (TextWriter, Configuration) to (TextWriter, CsvConfiguration).
public CsvSerializer(TextWriter writer, Configuration configuration)public CsvSerializer(TextWriter writer, CsvConfiguration configuration)CsvSerializer(TextWriter, CsvConfiguration, bool)Breaking
The parameters changed from (TextWriter, Configuration, bool) to (TextWriter, CsvConfiguration, bool).
public CsvSerializer(TextWriter writer, Configuration configuration, bool leaveOpen)public CsvSerializer(TextWriter writer, CsvConfiguration configuration, bool leaveOpen)CsvSerializer(TextWriter, CultureInfo)Breaking
The parameters changed from (TextWriter, bool) to (TextWriter, CultureInfo).
public CsvSerializer(TextWriter writer, bool leaveOpen)public CsvSerializer(TextWriter writer, CultureInfo cultureInfo)Removed
Added
CsvWriterclass4 breaking1 removed3 changed3 added
CsvWriter(TextWriter, CsvConfiguration)Breaking
The parameters changed from (TextWriter, Configuration) to (TextWriter, CsvConfiguration).
public CsvWriter(TextWriter writer, Configuration configuration)public CsvWriter(TextWriter writer, CsvConfiguration configuration)CsvWriter(TextWriter, CsvConfiguration, bool)Breaking
The parameters changed from (TextWriter, Configuration, bool) to (TextWriter, CsvConfiguration, bool).
public CsvWriter(TextWriter writer, Configuration configuration, bool leaveOpen)public CsvWriter(TextWriter writer, CsvConfiguration configuration, bool leaveOpen)CsvWriter(TextWriter, CultureInfo)Breaking
The parameters changed from (TextWriter, bool) to (TextWriter, CultureInfo).
public CsvWriter(TextWriter writer, bool leaveOpen)public CsvWriter(TextWriter writer, CultureInfo cultureInfo)Removed
Added
Factoryclass6 breaking3 removed3 changed3 added
CreateParser(TextReader, CsvConfiguration)Breaking
The parameters changed from (TextReader, Configuration) to (TextReader, CsvConfiguration).
public virtual IParser CreateParser(TextReader reader, Configuration configuration)public virtual IParser CreateParser(TextReader reader, CsvConfiguration configuration)CreateReader(TextReader, CsvConfiguration)Breaking
The parameters changed from (TextReader, Configuration) to (TextReader, CsvConfiguration).
public virtual IReader CreateReader(TextReader reader, Configuration configuration)public virtual IReader CreateReader(TextReader reader, CsvConfiguration configuration)CreateWriter(TextWriter, CsvConfiguration)Breaking
The parameters changed from (TextWriter, Configuration) to (TextWriter, CsvConfiguration).
public virtual IWriter CreateWriter(TextWriter writer, Configuration configuration)public virtual IWriter CreateWriter(TextWriter writer, CsvConfiguration configuration)Removed
Added
IFactoryinterface6 breaking3 removed3 changed3 added
CreateParser(TextReader, CsvConfiguration)Breaking
The parameters changed from (TextReader, Configuration) to (TextReader, CsvConfiguration).
IParser CreateParser(TextReader reader, Configuration configuration)IParser CreateParser(TextReader reader, CsvConfiguration configuration)CreateReader(TextReader, CsvConfiguration)Breaking
The parameters changed from (TextReader, Configuration) to (TextReader, CsvConfiguration).
IReader CreateReader(TextReader reader, Configuration configuration)IReader CreateReader(TextReader reader, CsvConfiguration configuration)CreateWriter(TextWriter, CsvConfiguration)Breaking
The parameters changed from (TextWriter, Configuration) to (TextWriter, CsvConfiguration).
IWriter CreateWriter(TextWriter writer, Configuration configuration)IWriter CreateWriter(TextWriter writer, CsvConfiguration configuration)Removed
Added
IReaderinterface4 added
Added
IWriterinterface2 added
Added
ReadingContextclass1 breaking1 changed
ReadingContext(TextReader, CsvConfiguration, bool)Breaking
The parameters changed from (TextReader, Configuration, bool) to (TextReader, CsvConfiguration, bool).
public ReadingContext(TextReader reader, Configuration configuration, bool leaveOpen)public ReadingContext(TextReader reader, CsvConfiguration configuration, bool leaveOpen)WritingContextclass1 breaking1 changed
WritingContext(TextWriter, CsvConfiguration, bool)Breaking
The parameters changed from (TextWriter, Configuration, bool) to (TextWriter, CsvConfiguration, bool).
public WritingContext(TextWriter writer, Configuration configuration, bool leaveOpen)public WritingContext(TextWriter writer, CsvConfiguration configuration, bool leaveOpen)CsvHelper.Configuration
ClassMapclass4 breaking2 removed2 changed2 added
AutoMapConstructorParameters(ClassMap, CsvConfiguration, LinkedList<Type>, int)Breaking
The parameters changed from (ClassMap, Configuration, LinkedList<Type>, int) to (ClassMap, CsvConfiguration, LinkedList<Type>, int).
protected virtual void AutoMapConstructorParameters(ClassMap map, Configuration configuration, LinkedList<Type> mapParents, int indexStart = 0)protected virtual void AutoMapConstructorParameters(ClassMap map, CsvConfiguration configuration, LinkedList<Type> mapParents, int indexStart = 0)AutoMapMembers(ClassMap, CsvConfiguration, LinkedList<Type>, int)Breaking
The parameters changed from (ClassMap, Configuration, LinkedList<Type>, int) to (ClassMap, CsvConfiguration, LinkedList<Type>, int).
protected virtual void AutoMapMembers(ClassMap map, Configuration configuration, LinkedList<Type> mapParents, int indexStart = 0)protected virtual void AutoMapMembers(ClassMap map, CsvConfiguration configuration, LinkedList<Type> mapParents, int indexStart = 0)Removed
Added
ClassMapCollectionclass1 breaking1 changed
ClassMapCollection(CsvConfiguration)Breaking
The parameters changed from (Configuration) to (CsvConfiguration).
public ClassMapCollection(Configuration configuration)public ClassMapCollection(CsvConfiguration configuration)ISerializerConfigurationinterface2 added
Added
Added types (3)
Removed types (1)
CsvHelper.Configuration.Attributes
BooleanFalseValuesAttributeclass1 changed1 added
BooleanFalseValuesAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class BooleanFalseValuesAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class BooleanFalseValuesAttribute : Attribute, IMemberMapperAdded
BooleanTrueValuesAttributeclass1 changed1 added
BooleanTrueValuesAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class BooleanTrueValuesAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class BooleanTrueValuesAttribute : Attribute, IMemberMapperAdded
ConstantAttributeclass1 changed1 added
ConstantAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class ConstantAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class ConstantAttribute : Attribute, IMemberMapperAdded
CultureInfoAttributeclass1 changed1 added
CultureInfoAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class CultureInfoAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class CultureInfoAttribute : Attribute, IMemberMapperAdded
DateTimeStylesAttributeclass1 changed1 added
DateTimeStylesAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class DateTimeStylesAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class DateTimeStylesAttribute : Attribute, IMemberMapperAdded
DefaultAttributeclass1 changed1 added
DefaultAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class DefaultAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class DefaultAttribute : Attribute, IMemberMapperAdded
FormatAttributeclass1 changed1 added
FormatAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class FormatAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class FormatAttribute : Attribute, IMemberMapperAdded
HeaderPrefixAttributeclass1 changed1 added
HeaderPrefixAttribute
The type now implements IMemberReferenceMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class HeaderPrefixAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class HeaderPrefixAttribute : Attribute, IMemberReferenceMapperAdded
IgnoreAttributeclass1 changed1 added
IgnoreAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class IgnoreAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class IgnoreAttribute : Attribute, IMemberMapperAdded
IndexAttributeclass1 changed1 added
IndexAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class IndexAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class IndexAttribute : Attribute, IMemberMapperAdded
NameAttributeclass1 changed1 added
NameAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class NameAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class NameAttribute : Attribute, IMemberMapperAdded
NameIndexAttributeclass1 changed1 added
NameIndexAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class NameIndexAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class NameIndexAttribute : Attribute, IMemberMapperAdded
NullValuesAttributeclass1 changed1 added
NullValuesAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class NullValuesAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class NullValuesAttribute : Attribute, IMemberMapperAdded
NumberStylesAttributeclass1 changed1 added
NumberStylesAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class NumberStylesAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class NumberStylesAttribute : Attribute, IMemberMapperAdded
OptionalAttributeclass1 changed1 added
OptionalAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class OptionalAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class OptionalAttribute : Attribute, IMemberMapperAdded
TypeConverterAttributeclass1 changed1 added
TypeConverterAttribute
The type now implements IMemberMapper.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class TypeConverterAttribute : Attribute[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class TypeConverterAttribute : Attribute, IMemberMapperAdded
Added types (2)