开发者

How to mask the value of a member variable in a List of objects using LINQ?

I have a table 开发者_JAVA技巧which I'm displaying in a grid. I'm being asked to mask the value of certain column if another value in that same row meets some condition.

Take for example:

public class Container
{
     public string Name { get; set; }
     public int Volume { get; set; }
}

IQueryable<Container> myContainerList;
// Imagine some code to populate the object

Currently, I'm masking the Volume field like so:

var filteredList = from container in myContainerList
                   let vol = container.Name.ToUpper().Contains("SPECIAL") ? 
                                                       -1 : container.Volume
                   select new Container()
                   {
                       Name = Name,
                       Volume = vol
                   };

This successfully masks the volume of any container with the name "special" in it, but this seems inefficient to me.

Is there a better way of going about this?


I'd add another property to the Container class:

public string MaskedVol
{
  get 
  { 
    return (Name.IndexOf("SPECIAL", StringComparison.OrdinalIgnoreCase) != -1 ) ? "--" : Volume.ToString();
  }
}


I agree with Sean that adding a readonly property is probably the best option. If you don't want to change the Container class, than you can simplify your linq query a little bit:

var filteredList = myContainerList.Select(c => new Container {
    Name = c.Name,
    Volume = c.Name.ToUpper().Contains("SPECIAL") ? -1 : c.Volume
});


Why does this seem inefficient to you?
For each item, exactly one check is performed, so I can't see any way of speeding up the process.

You can make it a bit faster and less resource-consuming by using IndexOf instead of creating a new string with ToUpper and calling Contains.

Then decide whether it is Component's responsiblity to mask Volume.
If it is, declare a special property in it to remove clutter in query:

public class Container
{
    public string Name { get; set; }
    public int Volume { get; set; }

    public int MaskedVolume {
        get {
            return (Name.IndexOf ("SPECIAL", StringComparison.OrdinalIgnoreCase) >= 0)
                ? Volume
                : -1;
        }
    }
}

If it's not Container's responsibility to know about masking, I agree with Elian that lambda is a better fit than let:

var filteredList = list.Select (c =>
    new Container {
        Name = c.Name,
        Volume = (c.Name.IndexOf ("SPECIAL", StringComparison.OrdinalIgnoreCase) >= 0)
                     ? c.Volume
                     : -1
    });

What alerts me, though, is the fact you create another instance of Component just to display it in a list view. Is this true? It seems like Component is part of business logic, and surely from business logic point of view new Components don't get created each time a list view is populated.

Maybe you should reconsider your solution in this case. Can you give us more details about how Component is used in the application?

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜