I have a piece of code I am currently refactoring, but I can’t find documentation about what a line in one of the ClassMap
s is doing exactly. I try to get rid of the ClassMap
s and replace them with attributes on the actual classes, but I’m unsure what would be the equivalent of this line.
This is (a simplified version of) the ClassMap
I’m wondering about:
public class MyClassMap : ClassMap<MyCsvClass>
{
public MyClassMap()
{
Map(t => t.MyNullableDoubleProperty).Name("MyCustomName").TypeConverterOption.Format("0.0".PadRight(100, '#'));
}
}
I’m unsure about the TypeConverterOption
part. My best guess is that it ensures that the output for the double property has a decimal point and at least one decimal place, but at most 100 additional decimal places. Is this correct? And more importantly: How can I do the same with an attribute for this property?
3
It has nothing to do with the CSV-Helper. It is the String.PadRight Method.
It appends as many '#'
to the right of the string "0.0"
as required to get a total string length of 100. The result will be "0.0#######...####"
with a total length of 100.
As a numeric format, this means that the number will have at least one digit before and after the decimal point and possibly more optional digits to the right but a maximum of 98 (= 100 – 2 for "0."
). double
values are limited to 15 significant decimal digits.
Example with 2.0/3e50
:
"0.00000000000000000000000000000000000000000000000000666666666666667"
Length: 67
See also: Custom numeric format strings
1
@OlivierJacot-Descombes already answered
What does the
Format("0.0".PadRight(100, '#'))
do?
so I’ll answer
How can I do the same with an attribute?
You can use the FormatAttribute
. Unfortunately, you can’t use PadRight()
in an attribute expression, so you would have to write out all of the # signs.
void Main()
{
var records = new List<Foo> { new Foo { Id = 1, MyDouble = 2.0/3e50}};
using var csv = new CsvWriter(Console.Out, CultureInfo.InvariantCulture);
csv.WriteRecords(records);
}
public class Foo
{
public int Id { get; set; }
[Name("MyCustomName")]
[Format("0.0#########################################################################################################################")]
public double MyDouble { get; set; }
}
The other option would be to create a custom TypeConverter
.
void Main()
{
var records = new List<Foo> { new Foo { Id = 1, MyDouble = 2.0/3e50}};
using var csv = new CsvWriter(Console.Out, CultureInfo.InvariantCulture);
csv.WriteRecords(records);
}
public class Foo
{
public int Id { get; set; }
[Name("MyCustomName")]
[TypeConverter(typeof(DoublePadRightConverter))]
public double MyDouble { get; set; }
}
public class DoublePadRightConverter : DoubleConverter
{
public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
{
if (value is double d)
{
return d.ToString("0.0".PadRight(100, '#'), memberMapData.TypeConverterOptions.CultureInfo);
}
return base.ConvertToString(value, row, memberMapData);
}
}
1