Magnus Mårtensson
Microsoft Regional Director, Azure MVP, CEO Loftysoft
Avirag Jain
Director & CTO R Systems
Mahesh Chand
Founder C# Corner, CEO Mindcracker
Chris Gali
CEO & Co-Founder Graphite
Subinder Khurana
Chief Architect StoryProcess, Founder NASSCOM DeepTech Club
Bryan Rishforth
Investor, Chairman Graphite
Bryn Everson
Director Biz Dev Graphite
Raj Tiwari
Digital Transformation Leader, Futurist and Visionary
Joseph Guadagno
Microsoft MVP, Lead Quicken Loans
Nikita Sachdev
Entrepreneur, Blockchain Enthusiast & Advisor, Social Media Influencer
Doug Wagner
COO & Founder Adapt Technical Group
Ritesh Modi
Architect, Senior Evangelist, Cloud Architect
Crystal Wenrick
Director Communications Mindcracker
Allen O’Neill
Microsoft MVP, Consulting Engineer/Architect
Praveen Kumar
CEO MCN Solutions
Chris Love
Founder Love2Dev, Microsoft MVP, Author
Sanjay Vyas
Microsoft Regional Director, Microsoft MVP, Founder & CEO SkillLabs Technologies
Veena Sarda
Deep Learning Consultant, Author
Sekhar Srinivasan
C# Corner MVP, Microsoft Certified Trainer, Pluralsight Author
Lalit Bansal
Founder & CEO - EIY SYS
Navdeep Garg
CEO Revinfotech
Prakash Tripathi
Tech Manager/Leader, Microsoft MVP, Blogger
Bhavna Jain
Breakthrough Consultant
Naveen Sharma
Enterprise Architect, Leadership Coach, Author
Vidya Vrat Agarwal
Principal Architect, Microsoft MVP, Author
Sheetal Agarwal
Founder Clownselors, Medical Clown, Trainer
Abhishek Kant
Founder GTM Catalyst
Vishnu Saran
Founder & CEO VoiceQube
Sandeep Soni
Founder & CEO Deccansoft, Microsoft Certified Trainer
Parveen Malik
AVP InfoSec & Vulnerability Management, Information Security Expert
Nitin Pandit
Microsoft MVP, Developer Evangelist, Author
Niloshima Srivastava
C# Corner MVP, Tech Architect, Trainer, Blogger
Bala Chirtsabesan
Senior Software Engineer at Microsoft, Author
Manoj Mittal
Sr. Technical Architect, C# Corner MVP, Author
Chandni Di
Co-Founder Voice of Slum
Vithal Wadje
Technical Lead, Microsoft MVP, Author
Shivam Ahuja
Founder SkillCircle, Business Mentor
Chervine Bhiwoo
Solution Architect, Microsoft MVP, Author
Saurabh Jain
Vice President Paytm, Founder Fun2Do Labs, Author
Vinay Solanki
Head IoT at Lenovo, Founder IoT-NCR
Anshu kumari
Founder Blockchainkids, Inventor, Trainer
Amit Singal
CEO Startup Buddy
Dev Pratap
Co-Founder & CEO Voice of Slum
Amey Vartak
Technology Consultant, Full Stack Developer, C# Corner MVP, Author
Viswanatha Swamy
Principal Software Engineer, C# Corner MVP, Author
Sanket Verma
Research Engineer @ Ballistics (Forensics) and Chair, PyData Delhi
Sourabh Somani
Lead Developer, Microsoft MVP, Author
Abhishek Mishra
Software Architect, C# Corner MVP, Author
Siddharth Vaghasia
Technical Consultant, C# Corner MVP, Blogger
Bassam Alugili
Senior Software Specialist, Database Expert
S Ravi Kumar
Solution Architect, C# Corner MVP, Author
Sundaram Subramanian
Full Stack Developer, C# Corner MVP, Speaker
Deepesh Somani
Solution Architect, Microsoft MVP, Author
Debasis Saha
Technical Project Manager, C# Corner MVP, Blogger, Author
Vipul Jain
Software Architect, C# Corner MVP, Author
Akshay Patel
Technical Architect, Microsoft Certified Trainer, C# Corner MVP, Author
Stephen Simon
RPA Developer, Evangelist, Author
Vivek Sharma
Founder Kingster636, AR/VR Specialist
Jeetendra Gund
Technical Lead, C# Corner MVP, Author
Sujal Beniwal
AI Enthusiast, Student
M Viknaraj
Microsoft MVP, Azure Architect, Author
Prasham Sabadra
Software Architect, C# Corner MVP, Trainer, Author
Aakash Maurya
Senior Developer, C# Corner MVP, Speaker
Ankit Sharma
Senior Software Engineer, C# Corner MVP, Author
Mangesh Gaherwar
Team Lead, C# Corner MVP, Author
Viral Jain
Technical Consultant, C# Corner MVP, Author
Bhasker Das
Solution Architect, Evangelist
Manish Dwivedi
Associate Project Manager
Ck Nitin
Programmer, Author
Rohit Gupta
Technical Trainer, Author
Manish Tewatia
Full-stack Marketer, UX Designer
Bhavya Gaur
Technical Illustrator
Rohit Tomar
SEO/SMO Expert
Web Track
Cloud & Data Track
Dev Track
Registration & Breakfast
Future of Desktop Apps with JS (ElectronJs)
Nitin Pandit
Building Serverless Microservices Using Microsoft Azure
Vithal Wadje
Innovating RPA: A Robot for Every Person
Stephen Simon
Managing Cloud Storage Accounts using Logic Apps
Viknaraj Manogararajah
Data visualization using Python
Sekhar Srinivasan
Going Cross platform with AR Foundation
Vivek Sharma
Keynote
Managing your Azure dependencies in ASP.NET Core apps using VS
Bala Chirtsabesan
Securing Applications on Intelligent Azure
Abhishek Mishra
Getting started with Blazor the Framework of Future
S Ravi Kumar
Lunch
Build Progressive Web Apps using Angular 9
Debasis Saha
Build and deploy to any platform using Azure DevOps
Chervine Bhiwoo
Deep Dive in Azure Service Bus
Akshay Patel
Build a Native Mobile Application using React Native and JavaScript
Joseph Guadagno
Making sense of Web Job, Web Job SDK and Functions in Azure
Prakash Tripathi
CloudFront Distribution in AWS
Viral Jain
Tea Break
Introduction to PowerBI
Aakash Maurya
Build Advanced SPFx solutions with React and Graph API
Siddharth Vaghasia
Build Business Intelligence Analyst (BIA) Skills
Sundaram Subramanian
Deep dive of Power Platform – AI BUILDER
Prasham Sabadra
Panel 1
What's new in SharePoint development
Vipul Jain
Build a SSO (Single Sign On) based Native JavaScript application with Microsoft Identity within 10 minutes
Manoj Mittal
Panel 2
Applications and working of AI
Veena Sarda
Deploying serverless API's with .Net core 3.0 on AWS & Azure
Amey Vartak
Panel 3
Blockchain with .NET Core (Ark)
Anshu Kumari
Closing Note & Prize Distribution
Dev Track
Cloud Track
Architecture Track
Emerging Tech Track
Registration & Breakfast
Creating Full-Stack Web Apps Using Server-Side Blazor
Ankit Sharma
Real time face recognition with MS Cognitive Services
Niloshima Srivastava
Building Scalable APIs with GraphQL
Jeetendra Gund
Future of development with AI and Blockchain
Navdeep Garg
Debugging Tips and Tricks with Visual Studio 2019
Joseph Guadagno
Azure Containers
Abhishek Kant
Enterprise Architecture
Naveen Sharma
Bot Framework - learn it fast and look like a boss!
Allen O’Neill
Keynote
.Net Core & C# 8 Performance
David McCarter
Working with Azure kubernetes services
Ritesh Modi
Becoming an Architect
Vidyavrat Agarwal
Why Techies Need to Learn Product Management
Saurabh Jain
Lunch
Build a rules engine in .Net Core
Sanjay Vyas
Building CI and CD Pipeline using Azure DevOps
Sandeep Soni
Entity Framework Core - Tips and Tricks, Performance Optimization, and Tuning
Bassam Alugili
Hacking your way into Data Science
Sanket Verma
Speed up your .Net Core Website
Sourabh Somani
Azure
Magnus Mårtensson
Demystifying Open Distro for Elasticsearch
Suman Debnath
Future of Data
Shivam Ahuja
Tea Break
gRPC with C# and .Net Core
Mangesh Gaherwar
Panel 1
Essentials of Cloud security
Parveen Malik
Power platform and Dynamics 365
Deepesh Somani
Microservices - the gRPC Way
Viswanatha Swamy
Panel 2
Reserved
Reserved
Closing Note & Prize Distribution
Building a dependable CSV parser with modern C#
CSV looks simple until a field contains a comma, a quotation mark, a line break, or an unexpected character encoding. A parser that works for a small sample can fail when it receives an export from accounting software, a spreadsheet edited in Melbourne, or a large data file uploaded overnight in Sydney.
Modern C# gives you useful tools for solving this problem cleanly. Raw string literals make test fixtures readable, while C# 12 features such as collection expressions, primary constructors, improved pattern matching, and span-friendly APIs help reduce ceremony around the parser itself.
The key is to treat CSV as a small language rather than as text that can be safely split with string.Split(','). The parser must track whether it is inside quoted content, preserve embedded commas and newlines, and report malformed input with enough context for an application team to fix the source file.
This example builds a reusable, UTF-8-friendly parser for .NET 8. It focuses on correctness and clear design, with practical details that matter in Australian systems, including dd/MM/yyyy dates, GST-related exports, and postcodes such as 0800 whose leading zero must be preserved.
Why splitting on commas fails
A CSV record can contain commas inside quoted fields. For example, an Australian customer address might be written as "14 George Street, The Rocks, NSW". Splitting the line at every comma would incorrectly turn one address into several columns.
Quotation marks also have a defined escaping rule. A literal quotation mark inside a quoted field is represented by two quotation marks:
"Customer said ""call after lunch"""
The resulting field value should be:
Customer said "call after lunch"
A record may span multiple physical lines as well. A notes field containing a line break is valid when the entire field is quoted. This is common in CRM exports and support systems where staff add several lines of notes during the arvo.
A useful parser therefore needs three states:
- It is reading an ordinary field.
- It is reading a quoted field.
- It has just seen a quotation mark inside a quoted field and must decide whether it is escaped or closing.
That small state machine is easier to test and maintain than a collection of regular expressions.
Modelling parser results
A parser should make its output explicit. Returning List<string[]> is convenient, but it gives callers no indication of whether a row was malformed or whether columns have consistent names. A small record type provides a stronger boundary between parsing and application logic.
public sealed record CsvRow(
int LineNumber,
IReadOnlyList<string> Fields);
public sealed record CsvParseError(
int LineNumber,
string Message);
The LineNumber value refers to the physical line where the parser detected the issue. A quoted field can occupy several lines, so production systems may also track the starting line of the record. That refinement makes diagnostics more precise for large imports.
For a first implementation, expose rows as an iterator. This allows callers to process a large file without loading the entire export into memory:
public sealed record CsvDocument(
IReadOnlyList<string> Headers,
IEnumerable<CsvRow> Rows);
If the input is a sales export, the application can map each row into a typed model after parsing. Keep conversion separate from tokenisation. The parser should understand commas and quotes; a mapper should understand dates, decimal amounts, tax codes, and business rules.
Using raw strings for readable test data
Raw string literals arrived in C# 11, so they are available when a C# 12 project targets a suitable .NET SDK. They are especially valuable for CSV tests because ordinary string literals require escaped quotation marks and newline characters.
const string CsvSample = """
CustomerId,Name,Postcode,Notes
1001,"Nguyen, Minh",3000,"Prefers email"
1002,"O'Connor, Siobhan",0800,"Call after 3pm"
1003,"Taylor, Alex",2000,"Address confirmed
during the arvo"
""";
The content is visually close to the input file. The 0800 postcode is intentionally kept as text. Converting it to an integer would turn it into 800, which is incorrect for a Northern Territory address.
Raw strings are also helpful when testing escaped quotation marks:
const string QuotedText = """
Id,Comment
7,"The customer said ""approved"""
""";
For test data containing several quotation marks at the beginning or end of a line, increase the number of $ or quote characters used by the raw string delimiter. This avoids awkward escaping while keeping the fixture easy to review in source control.
Implementing the state machine
The parser can consume a TextReader, which supports files, memory streams, HTTP responses, and test strings. The implementation below reads one character at a time so it can recognise commas, line endings, and quoted content without making assumptions about physical lines.
public sealed class CsvParser
{
private readonly TextReader _reader;
public CsvParser(TextReader reader) => _reader = reader;
public IEnumerable<IReadOnlyList<string>> ReadRows()
{
var fields = [];
var field = new StringBuilder();
var inQuotes = false;
var sawAnyCharacter = false;
while (_reader.Read() is int value && value >= 0)
{
sawAnyCharacter = true;
var character = (char)value;
if (inQuotes)
{
if (character == '"')
{
if (_reader.Peek() == '"')
{
_reader.Read();
field.Append('"');
}
else
{
inQuotes = false;
}
}
else
{
field.Append(character);
}
continue;
}
switch (character)
{
case '"':
if (field.Length != 0)
throw new FormatException("A quote appeared inside an unquoted field.");
inQuotes = true;
break;
case ',':
fields.Add(field.ToString());
field.Clear();
break;
case '\r':
if (_reader.Peek() == '\n')
_reader.Read();
fields.Add(field.ToString());
field.Clear();
yield return fields.ToArray();
fields.Clear();
break;
case '\n':
fields.Add(field.ToString());
field.Clear();
yield return fields.ToArray();
fields.Clear();
break;
default:
field.Append(character);
break;
}
}
if (inQuotes)
throw new FormatException("The file ended inside a quoted field.");
if (sawAnyCharacter && (field.Length > 0 || fields.Count > 0))
{
fields.Add(field.ToString());
yield return fields.ToArray();
}
}
}
This version handles CRLF files from Windows and LF files from Unix-like systems. It also supports commas and line breaks inside quoted fields. The fields = [] expression is a C# 12 collection expression; the compiler infers the target type from the field declaration.
A production parser should decide how to handle a trailing comma, empty files, blank records, and whitespace after a closing quote. Strict mode can reject invalid input immediately. Lenient mode can accept selected variations while recording warnings. Make that policy explicit instead of allowing accidental behaviour.
Adding headers and typed records
Many CSV exports use the first row as a header. Before mapping data, validate the header names and count. A file with CustomerId,Name,Postcode should not silently be processed as though it contained Id,Customer,Address.
public sealed record Customer(
string CustomerId,
string Name,
string Postcode,
string Notes);
static Customer ToCustomer(IReadOnlyList<string> row)
{
if (row.Count != 4)
throw new FormatException(
$"Expected four columns but received {row.Count}.");
return new Customer(
CustomerId: row[0],
Name: row[1],
Postcode: row[2],
Notes: row[3]);
}
Parsing values should use culture deliberately. Australian business exports commonly use dates such as 31/01/2025, while APIs often use ISO 8601 values such as 2025-01-31. Choose the expected format rather than relying on the machine’s current culture, particularly when a service runs in a different Azure region.
if (!DateOnly.TryParseExact(
value,
"dd/MM/yyyy",
CultureInfo.GetCultureInfo("en-AU"),
DateTimeStyles.None,
out var invoiceDate))
{
throw new FormatException($"Invalid Australian date: {value}");
}
For currency, use decimal, not double, and define whether values include GST. An ATO-facing workflow may need a tax-inclusive amount, a GST component, and a tax code as separate fields. Those decisions belong in the domain mapper, not in the low-level CSV reader.
Handling encoding, performance, and security
Most modern exports should be read as UTF-8. A UTF-8 file can start with a byte order mark, and the first header may contain that marker if it is handled incorrectly. When opening a file, specify the encoding and consider removing a leading \uFEFF from the first field.
using var stream = File.OpenRead("customers.csv");
using var reader = new StreamReader(
stream,
new UTF8Encoding(encoderShouldEmitUTF8Identifier: false),
detectEncodingFromByteOrderMarks: true);
var parser = new CsvParser(reader);
For large files, stream rows and process them in batches. Avoid calling ReadToEnd() when an import may contain hundreds of megabytes. A streaming approach suits cloud workloads where an Azure Function or container receives an object from Blob Storage and sends validated records to a queue.
CSV can also be a security boundary. Spreadsheet applications may interpret values beginning with =, +, -, or @ as formulas when a generated CSV is opened. If your application exports user-controlled data, consider prefixing dangerous values or documenting a safe import workflow. Never assume that a file supplied by a trusted business partner is harmless.
If throughput becomes important, benchmark the parser with realistic data. StringBuilder is easy to understand, but a specialised implementation using spans or pooled buffers may reduce allocations. Optimise after measuring, because clarity is valuable in data-import code that must be supported across Australian business hours and regional deployments.
Testing malformed and real-world input
A parser test suite should include valid and invalid records. Raw strings make each case readable and keep the test focused on behaviour rather than escape sequences.
[Fact]
public void Preserves_commas_quotes_and_newlines()
{
const string input = """
Id,Description
1,"One, two"
2,"He said ""ready"""
3,"First line
Second line"
""";
using var reader = new StringReader(input);
var rows = new CsvParser(reader).ReadRows().ToArray();
Assert.Equal("One, two", rows[1][1]);
Assert.Equal("He said \"ready\"", rows[2][1]);
Assert.Equal("First line\nSecond line", rows[3][1]);
}
Also test an empty final field, a final record without a newline, CRLF input, a blank file, an unmatched quote, a quote appearing in unquoted data, and rows with inconsistent column counts. Property-based tests can generate random fields containing commas, quotes, and line endings, then verify that writing and reading produces the original values.
Use representative local data rather than only synthetic words. Include Australian postcodes such as 3000, 2000, and 0800; suburb names containing spaces; state abbreviations; and dates in the format used by the source system. A file produced in Perth may use LF line endings, while a Windows desktop export in Brisbane may use CRLF. Correctness should not depend on where the export was created.
Choosing an approach for your application
A handwritten parser is appropriate when you need a small dependency-free component, strict control over validation, or a focused learning implementation. A mature library is usually preferable when the application must support dialect options, unusual delimiters, comments, configurable quoting, or extensive error recovery.
The important design choice is to keep parsing, validation, and business mapping separate. That separation makes it easier to replace the parser, add a schema version, or route rejected rows to a review queue without changing the customer or invoice model.
| Approach | Strengths | Trade-offs | Suitable use |
|---|---|---|---|
string.Split |
Very short and familiar | Breaks on quoted commas, quotes, and multiline fields | Controlled one-line samples only |
| Handwritten state machine | No external package, transparent behaviour, easy to customise | Requires thorough tests and maintenance | Small services and learning projects |
| Dedicated CSV library | Mature dialect support, mapping features, and diagnostics | Adds a dependency and configuration surface | Production imports with varied suppliers |
| Database bulk import | High throughput for supported formats | Less flexible validation and error reporting | Large, stable files headed directly to a database |
A dependable C# 12 CSV workflow uses raw strings where they improve test readability, modern collection syntax where it reduces noise, and a deliberate state machine for the actual format rules. With explicit culture, encoding, schema validation, and streaming, the parser can handle everyday files from Australian operations as reliably as carefully designed API payloads.
1, CBD, Maharaj Surajmal Road, Near Yamuna Sports Complex, Delhi, 110032
GENERAL QUERIES
Manish Tewatia
manish@csharpcon.com
+91-9718-431-042
TICKET QUERIES
Atul Gupta
conference@csharpcon.com
+91-9910-125-804