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 Component
s 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?
精彩评论