Method chaining generic list extensions

主宰稳场 提交于 2019-12-08 06:27:45

问题


I have a List of a "complex" type - an object with a few string properties. The List itself is a property of another object and contains objects of a variety of types, as shown in this abbreviated class structure:

Customer {
   public List<Characteristic> Characteristics;
   .
   .
   .
}

Characteristic {
   public string CharacteristicType;
   public string CharacteristicValue;
}

I'd like to be able to collect a List of the values of a given type of Characteristics for the current Customer, which I can do in a 2-step process as follows:

List<Characteristic> interestCharacteristics = customer.Characteristics.FindAll(
   delegate (Characteristic interest) {
      return interest.CharacteristicType == "Interest";
   }
);

List<string> interests = interestCharacteristics.ConvertAll<string>(
   delegate (Characteristic interest) {
      return interest.CharacteristicValue;
   }
);

That works fine, but it seems like a long way around. I'm sure I must be missing a simpler way of getting to this list, either by chaining together the FindAll() and Convert() methods, or something else I'm overlooking entirely.

For background, I'm working in .Net 2.0, so I'm limited to the .Net 2 generics, and the Characteristic class is an external dependency - I can't change it's structure to simplify it, and there are other aspects of the class that are important, just not in relations to this problem.

Any pointers or additional reading welcomed.


回答1:


Here's a generator implementation

public static IEnumerable<string> GetInterests(Customer customer)
{
    foreach (Characteristic c in customer.Characteristics)
    {
        if (c.CharacteristicType == "Interest")
            yield return c.CharacteristicValue;
    }
}

sadly 3.5 extension methods and lambda are out based on your requirements but for reference here's how to do it:

customer.Characteristics
    .Where(c => c.CharacteristicType == "Interest")
    .Select(c => c. CharacteristicValue);



回答2:


I would do some of the work manualy. By doing a FindAll first, and then a Convert, you're looping through your collection twice. It doesn't seem neccessary. If all you want at the end of the day, is a List of CharacteristicValue then just loop through your original collection, and add the CharacteristicValue to a List of each one that matches your criteria. Something like this:

     Predicate<Characteristic> criteria = delegate (Characteristic interest) 
     {
          return interest.CharacteristicType == "Interest";
     };
     List<string> myList = new List<string>();
     foreach(Characteristic c in customer.Characteristics)
     {
        if(criteria(c))
        {
            myList.Add(c.CharacteristicValue);
        }
     }



回答3:


Why not create a Dictionary<string, List<string>>, that way you can add "Interest" as the key, and a list of values as the value. For example:

Customer {
   public Dictionary<string, List<string>> Characteristics;
   .
   .
   .
}

...

Characteristics.Add("Interest", new List<string>());
Characteristics["Interest"].Add("Post questions on StackOverflow");
Characteristics["Interest"].Add("Answer questions on StackOverflow");
..

List<Characteristic> interestCharacteristics = Characteristics["Interest"];

Furthermore, if you wanted, you could limit your characteristics to a list of possible values by making it an enum, then use that as the data type of your dictionary's key:

public enum CharacteristicType
{
   Interest,
   Job,
   ThingsYouHate
//...etc
}

then declare your dictionary as:

public Dictionary<CharacteristicType, List<string>> Characteristics;
..
Characteristics.Add(CharacteristicType.Interest, new List<string>());
Characteristics[CharacteristicType.Interest].Add("Post questions on StackOverflow");
Characteristics[CharacteristicType.Interest].Add("Answer questions on StackOverflow");


来源:https://stackoverflow.com/questions/481175/method-chaining-generic-list-extensions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!