-1

I'm parsing a csv file in the manner described in this answer; it works great.

    public static List<string> MatchedLines(string[] MyArray)
    {
        List<string> csvFile = FileReadLinestoList(@"C:\Temp\MyFile.csv");
        //This doesn't work! //var lines = new IEnumerable<string>{from line in csvFile where line.Split(',')[0] == MyArray[0] && line.Split(',')[1] == MyArray[1] select line};
        var lines = from line in csvFile where line.Split(',')[0] == MyArray[0] && line.Split(',')[1] == MyArray[1] select line;
        return lines.ToList();
    }

However I don't like using 'var' unless the variable types are clear, which in this case they are not. How can I write this statement while explicitly declaring types for 'lines' and 'line'?

Community
  • 1
  • 1
xnguyeng
  • 113
  • 7
  • As a deleted answer pointed out, you can hover over `var` in Visual Studio, and see the actual type that will be assigned to the variable when it compiles. – Merlyn Morgan-Graham Apr 12 '16 at 23:11

3 Answers3

3

You can't directly create a instance of an interface, so new IEnumerable<string> simply doesn't work. But you can still type your variables as an interface simply by specifying the type like this:

IEnumerable<string> lines = from line in csvFile where line.Split(',')[0] == MyArray[0] && line.Split(',')[1] == MyArray[1] select line;

As a side note, in your current LINQ expression, you end up splitting the string twice. You can make this marginally more efficient by using a let clause:

IEnumerable<string> lines = 
    from line in csvFile 
    let parts = line.Split(new[] { ',' }, 3)
    where parts[0] == MyArray[0] && parts[1] == MyArray[1] 
    select line;
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • Thanks, I'm going to look into 'let' as I'm unfamiliar with it. What is the 3 referencing in 'let parts = line.Split(new[] { ',' }, 3)'? – xnguyeng Apr 13 '16 at 00:22
  • @xnguyeng That causes `Split` to looking for any more commas after the second one is found. e.g. `"1,2,3,4,5".Split(new[] { ',' }, 3)` returns `string[] { "1", "2", "3,4,5" }` – p.s.w.g Apr 13 '16 at 00:26
2

There is nothing wrong with having vars in your code, especially if you are dealing with LINQ queries. Should you decide to change your LINQ, you may need considerable changes to your type declaration, every single time. With var you can easily avoid the hassle. In many cases you don't need to know what the intermediate type is.

Victor Zakharov
  • 25,801
  • 18
  • 85
  • 151
  • 1
    +1; The final type is already explicit in the return type of the function, and in this specific case the intermediate types give you very little additional value because you're not performing intermediate transforms on them. – Merlyn Morgan-Graham Apr 12 '16 at 23:08
  • Makes sense. I just find when I'm debugging code I haven't looked at in a year or two that I prefer having explicit types wherever possible. I'm not opposed to 'var', but I prefer to use it when the types are explicit. But this might not be a best practice when implemented with LINQ, which I'm just starting to use. – xnguyeng Apr 13 '16 at 00:24
  • 1
    @xnguyeng explicit typing is very useful when you're just starting to learn C#, but as you become more comfortable, and especially if you're using an IDE like Visual Studio that has really good IntelliSense, you'll find that all those explicit types within your code tend to become noise. There are also plenty of times (e.g. with anonymous types) where you'll have to use `var`. – p.s.w.g Apr 13 '16 at 00:36
  • @xnguyeng: The key here is whether changing var to a static type declaration improves code readability. With LINQ in some (simple) cases yes, but in most cases no, because you'll see something like `IEnumerable>` (and that's not the worst example), and still want to look at the query. Without LINQ however, you are likely to be calling a function, like `var result = ProcessThisVariable(thisVariable)`. In this case if you had `Task result = ...` or `int result = ...` it really adds value, because you may **not** need to look at function definition. – Victor Zakharov Apr 13 '16 at 02:08
1

You're selecting line which is what you have as input so you start with a List<string> and end up with an IEnumerable<string>

you could thus change

var lines = from line in csvFile where line.Split(',')[0] == MyArray[0] && line.Split(',')[1] == MyArray[1] select line;

to

IEnumerable<string> lines = from line in csvFile where line.Split(',')[0] == MyArray[0] && line.Split(',')[1] == MyArray[1] select line;

However you could simplify the whole thing as the only other thing you're doing in this method is creating the csvFile variable and returning it as a list you could change the whole method to this :

public static List<string> MatchedLines(string[] MyArray)
{
    return (from line in FileReadLinestoList(@"C:\Temp\MyFile.csv")
            where line.Split(',')[0] == MyArray[0] && line.Split(',')[1] == MyArray[1] 
            select line).ToList();
}
Ronan Thibaudau
  • 3,413
  • 3
  • 29
  • 78
  • Thanks, I will probably use your simplification. I find it a bit less readable that way but definitely simpler as it saves a few lines. – xnguyeng Apr 13 '16 at 00:23