简体   繁体   中英

Rewrite type specific method as generic

I have a method (shown below) that I discovered can be reused in code elsewhere if I could turn it into a generic method, but am struggling with the syntax and could use a bit of help:

Sample:

private List<IndexEntry> AddParentReferences(List<IndexEntry> listWithoutParents)
        {
            List<IndexEntry> listWithParents = new List<IndexEntry>();

            foreach (IndexEntry currentEntry in listWithoutParents)
            {
                if (currentEntry.SubEntries == null || currentEntry.SubEntries.Count < 1)
                {
                    listWithParents.Add(currentEntry);
                    continue;
                }
                AddIndividualParentReference(currentEntry);
                listWithParents.Add(currentEntry);
            }
            return listWithParents;
        }

As you can see it's a simple method that takes in a List of IndexEntry types and enumerates that list adding references to parent items in the hierarchy. I've discovered that there are similarly designed types that will also need this sort of reference added at various points. I'd like to modify this code to take in a List and return an appropriate List where T is the type passed in. This seemed like a straight forward method to write, but I think I may be missing a simple sytax issue in my method definition. Can anyone enlighten me?

Thanks in advance,

Steve

When you make the method generic, you need to add a type constraint. If you don't, you can't access currentEntry.SubEntries as the compiler can't deduce that T has such a property. Thus, define an interface type as I've done below and then proceed like so:

List<T> AddParentReferences<T>(List<T> listWithoutParents) where T : IIndexEntry {
    List<T> listWithParents = new List<T>();

    foreach (T currentEntry in listWithoutParents) {
        if (currentEntry.SubEntries == null || currentEntry.SubEntries.Count < 1) {
            listWithParents.Add(currentEntry);
            continue;
        }
        AddIndividualParentReference(currentEntry);
        listWithParents.Add(currentEntry);
    }
    return listWithParents;
}

Here is the minimal interface you will need to make the above work:

interface IIndexEntry {
    IList<IIndexEntry> SubEntries;
}

You can make the method generic by appending <T> to the method name.

A problem is that you require T by having a SubEntries property. You can solve this problem by restricting T to types that implement an interface (see @jason's answer), or by passing in a predicate which tells whether an entry is empty or not:

private List<T> AddParentReferences<T>(
    List<T> listWithoutParents,
    Func<T, bool> isEmpty)
{
    List<T> listWithParents = new List<T>();
    foreach (T currentEntry in listWithoutParents)
    {
        if (isEmpty(currentEntry))
        {
            listWithParents.Add(currentEntry);
            continue;
        }
        AddIndividualParentReference(currentEntry);
        listWithParents.Add(currentEntry);
    }
    return listWithParents;
}

Usage:

AddParentReferences<IndexEntry>(
    indexEntries,
    e => e.SubEntries == null || e.SubEntries.Count < 1);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM