Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics basic usage

Tags:

c#

generics

I keep using 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 scratch 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 advise. Thank you!

like image 383
cilerler Avatar asked Jan 22 '13 15:01

cilerler


People also ask

What is the most important benefit of generics?

Advantages of using generics Generics allow the programmer to use the same method for Integer arrays, Double arrays, and even String arrays. Another advantage of using generics is that Individual typecasting isn't required. The programmer defines the initial type and then lets the code do its job.

What is generic explain?

/dʒəˈner·ɪk/ relating to or shared by a whole group of similar things; not specific to any particular thing: Jazz is a generic term for a wide range of different styles of music. Generic also means not having a trademark: a generic drug.


1 Answers

You cannot use new to create instances using generic types in this way1. Consider supplying a factory delegate to the 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 like so:

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

Alternatively, you can return an 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 could do:

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

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

For reference, this is how construction using generic types would look in the no-argument case:

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

2Even better would be an IEnumerable<IEnumerable<string>> assuming that your MyObject constructor accepts IEnumerable<string> as well.

like image 134
cdhowie Avatar answered Sep 28 '22 03:09

cdhowie