Its function seems to depend at least on the input file, but this file is requested by the function. You should follow the IoC principle and transfer the file from outside (via the function parameter).
var file = ConfigurationManager.AppSettings("catalogue-lines-import-file"); var lines = ImportCatalogueLines(file);
Maybe so, but not confusing, since your method is private, it should be pushed further, somewhere outside of the entire class …
if (header(i) == "catcode") catCodeColumn = i; if (header(i) == "prodcode") prodCodeColumn = i
It is impossible for Header (i) to correspond to two different values at the same time. Use else if or switch.
If you are superparanoid, you should also check that catCodeColumn and prodCodeColumn have not been assigned more than once. That would mean that there is a double column header (one that interests you).
catCodeColumn.HasValue == false || prodCodeColumn.HasValue == false
The comparison with false is redundant. Use the negation operator "!".
!catCodeColumn.HasValue || !prodCodeColumn.HasValue
Or use de Morgans' law
!(catCodeColumn.HasValue && prodCodeColumn.HasValue)
If a column value contains a comma (without talking about the quotes that are required to make it work), your implementation cannot handle it. Of course, only if the CSV ever contains such values. Even if this is not the case, users can change it at will. Time to get paranoid!
You shouldn't log everything within the function in the console. Especially if you have caught an exception, mute it and may return a reasonably created result. Instead, throw a custom exception and possibly have it carry the half-created list. But do not return with an incomplete result. And put the logging in a separate area.
That being said, I think your approach is reasonable. If you can't hard code or configure the columns that are staggered during compile time, you need to dynamically determine them … However, if you use a suitable CSV parser with additional features like header checking, the code looks very different, probably shorter …