开发者

How can I improve the readability of these linq statements?

开发者 https://www.devze.com 2023-03-12 00:41 出处:网络
I have a hierarchical data tree containing objects of a class called DataNode. Each DataNode contains a collection of Attribute objects.Each Attribute is essentially a key/value pair, with some helpe

I have a hierarchical data tree containing objects of a class called DataNode.

Each DataNode contains a collection of Attribute objects. Each Attribute is essentially a key/value pair, with some helper methods attached. For example, there is a helper method called EqualsCodeIndex(x) that matches a small collection x of int values to this attribute and returns true or false. All keys and values are strings, because the whole thing is based on a key/value store contained in a text file.

To simplify access to a particular DataNode, there is a dictionary in the DataTree class that maps all of the nodes in the tree to a unique code:

Dictionary<string, Dat开发者_Python百科aNode> Codes;

The resulting Linq statement to get to a specific Attribute value looks like this:

string AttributeValue = dataTree
    .Codes[@"R-1\CHE"]
    .Attributes
    .Single(x => x.EqualsCodeIndex(parentAttribute.CodeIndex))
    .Value.Trim();

This is not too bad if I only have to retrieve one or two attributes by code and code index, but it's not so good if I have to retrieve ten or more.

To attempt to simplify the statement, and allow for the possibility of EqualsCodeIndex returning false for all attributes in the collection, I added an extension method:

public static string AttributeValueMatching
    (this KeyValuePair<string, DataNode> pair, List<int> codeIndex)
{
    var attribute = pair.Value.Attributes
        .Single(x => x.EqualsCodeIndex(codeIndex))

    return attribute == null ? string.Empty : value;
}

This simplifies the original linq statement down to:

string attributeValue
    = dataTree.Codes[@"R-1\CHE"].AttributeValueMatching(codeIndex);

...which is better, but I have a feeling I'm missing something.


Are there problems with this approach? Is there a better, cleaner approach I haven't thought of, maybe making better use of indexers, or perhaps a fluent interface?


I think that making it into one method with two parameters would look slightly better:

Codes.AttributeValueMatching(@"R-1\CHE", codeIndex)

Or you could create a wrapper with an indexer:

CodesWrapper[@"R-1\CHE", codeIndex]


I don't have a direct answer to your whole question, but to the "problems with this approach" section I have a suggestion.

Be careful chaining statements after a SingleOrDefault() as it could potentially return null. If you are absolutely sure it will always have a single value, maybe just call Single() and deal with that missed expectation should it ever happen instead of a more generic NullReferenceException.

EDIT While writing the above post you made the same changes. Carry on...


Have you considered building an Extension Method of DataTree?

like

public static class DataTreeExtensions
   {
      public static string FetchByAttribute(this DataTree d, string Attribute)
      {
         string AttributeValue = d
                         .Codes[Attribute]
                         .Attributes
                         .Single(x => x.EqualsCodeIndex(parentAttribute.CodeIndex))
                         .Value.Trim();

            return AttributeValue

      }
   }

This will allow you to reuse "FetchByAttribute" at will as:

string myValue = myTree.FetchByAttribute(@"R-1\CHE");

Edited: changed from DataNode to DataTree...

0

精彩评论

暂无评论...
验证码 换一张
取 消