Reputation: 16290
I have a class:
public class Item {
public string Name { get; set; }
public object Value { get; set; }
}
And a collection of this class:
ICollection<Item> items;
Currently I have the following:
var item = items.Where(x => x.Name == "id").FirstOrDefault();
if (item != null)
item.Value = 1;
var item = items.Where(x => x.Name == "name").FirstOrDefault();
if (item != null)
item.Value = "Username";
//etc... for a number of items
Is it possible to an Expression and inline function to achieve the above but in much less and cleaner code?
Something like:
items.Set(x => x.Name == "id", value = 1);
items.Set(x => x.Name == "name", value = "username");
Upvotes: 0
Views: 165
Reputation: 7961
With slight addition to your class you can do it like this:
items.FirstOrDefault(x => x.Name == "id")?.SetValue(1);
Null-conditional operator ?.
(aka Elvis operator) protects you from the default/null value while calling SetValue(1)
but it does not allow for an assignment i.e. you cannot use property with it.
Your class will need SetValue
method:
public void SetValue(object arg)
{
Value = arg;
}
Upvotes: 1
Reputation: 7019
your syntax items.Set(x => x.Name == "id", value = 1);
doesn't look valid. But you can use items.Set(x => x.Name == "id", value : 1);
or items.Set(x => x.Name == "id", 1);
if you use this:
public static class ItemExtensions
{
public static void Set(this ICollection<Item> items, Func<Item, bool> predicate, object value)
{
var item = items.FirstOrDefault(predicate);
if (item != null)
item.Value = value;
}
}
Explanation
ICollection
. So, you would need to create an extension function. Where
function. Check the exact data type passed into the where. You would notice its Func<TSource, bool> predicate
. In this case, we know TSource
is Item
. FirstOrDefault
Upvotes: 0
Reputation: 4125
You can do something like that:
public static class Extensions
{
public static void Set<T>(
this ICollection<T> source,
Func<T, bool> predicate,
Action<T> action)
{
var item = source.FirstOrDefault(predicate);
if(item != null)
{
action(item);
}
}
}
Usage:
var collection = new List<User>()
{
new User { Name = "Pavel", Id = 1 },
new User { Name = "Anna", Id = 2}
};
collection.Set(q => q.Id == 1, w => w.Name = "Jacob");
Upvotes: 2
Reputation: 14992
I can think of a solution using .ToList()
and .ForEach()
, but that is not very readable.
using System;
using System.Linq;
using System.Collections.Generic;
public class Item {
public string Name { get; set; }
public object Value { get; set; }
}
public class Program
{
public static void Main()
{
var items = new List<Item>();
items.Add(new Item(){
Name = "test",
Value = 2
});
items.Add(new Item(){
Name = "id",
Value = 0
});
items.Where(i => i.Name == "id").ToList().ForEach(i => i.Value = 1);
Console.WriteLine(items[1].Name + " : " + items[1].Value);
}
}
Link to fiddle: https://ideone.com/7m66rg
Upvotes: 0