The main use of generics

I continue to use the function below in my classes and would like to write it as generics.

public static IEnumerable<MyObject> Get(string csvFile) { return csvFile .ReadAsStream() .SplitCrLf() .Where(row => !string.IsNullOrWhiteSpace(row)) .Select(row => new MyObject(row.Split(','))); } 

I scratched the code below but didn't work

 public static IEnumerable<T> Get<T>(string csvFile) { return csvFile .ReadAsStream() .SplitCrLf() .Where(row => !string.IsNullOrWhiteSpace(row)) .Select(row => new typeof(T)(row.Split(','))); } 

Please inform. Thanks!

+6
source share
1 answer

You cannot use new to instantiate using generic types this way 1 . Consider giving the delegate a factory function:

 public static IEnumerable<T> Get<T>(string csvFile, Func<string[], T> factory) { return csvFile .ReadAsStream() .SplitCrLf() .Where(row => !string.IsNullOrWhiteSpace(row)) .Select(row => factory(row.Split(','))); } 

Then you would call it that:

 var myObjects = Get("file.csv", row => new MyObject(row)); 

Alternatively, you can return IEnumerable<string[]> 2 and let the caller decide what to do with it:

 public static IEnumerable<string[]> Get(string csvFile) { return csvFile .ReadAsStream() .SplitCrLf() .Where(row => !string.IsNullOrWhiteSpace(row)) .Select(row => row.Split(',')); } 

Then the caller can do:

 var myObjects = Get("file.csv").Select(row => new MyObject(row)); 

1 You can specify the where T : new() constraint, and then create new instances using a common type, but only when it provides a constructor with no arguments; you cannot provide arguments when constructing generic types, and your use case seems to require it. Factory delegate is your best option here.

For reference, here is how building using generic types will look like in the case with no arguments:

 public static T Create<T>() where T : new() { return new T(); } 

2 Even better would be IEnumerable<IEnumerable<string>> , assuming your constructor MyObject also accepts IEnumerable<string> .

+11
source

All Articles