Reputation: 555
I would like to know what's a better way to improve this Linq set of code. Using xamarin forms and data binding. I need to pass individual fields to different labels and they all come from the same main list. I need to select those individuals items to pass them to each of the respective binding fields since each is expecting an only string.
var nameloc = MainList.Select(d => string.IsNullOrEmpty(d.name) ? "Not Available":d.name).FirstOrDefault();
var descrip = MainList.Select(d => string.IsNullOrEmpty(d.descr) ? "Not Available":d.descr).FirstOrDefault();
var cap = MainList.Select(d => string.IsNullOrEmpty(d.cap) ? "Not Available":d.cap).FirstOrDefault();
var ruls= MainList.Select(d => string.IsNullOrEmpty(d.ruls) ? "Not Available":d.ruls).FirstOrDefault();
var name = MainList.Select(d => string.IsNullOrEmpty(d.nameAddress) ? "Not Available":d.nameAddress).FirstOrDefault();
var email = MainList.Select(d => string.IsNullOrEmpty(d.EmailAddress) ? "Not Available":d.EmailAddress).FirstOrDefault();
var phone = MainList.Select(d => string.IsNullOrEmpty(d.phone) ? "Not Available":d.phone).FirstOrDefault();
LC = nameloc;
Description = descrip;
Cat = cap;
Rules = ruls;
Name = name;
Phone = phone;
email = email;
Upvotes: 0
Views: 82
Reputation: 6430
I think the minimalist approach would be using a lambda expression as parameter to get your values. So something like this might work -
//assumed class for demonstration only
public class Data
{
public string name { get; set; }
public string desc { get; set; }
}
//extension method
public static class ListExtensions
{
public static string GetFirstProperty(this List<Data> list, Expression<Func<Data, string>> predicate)
{
//you can ignore the compilation here, if you use Func<Data,string> instead of Expression<Func<Data,string>>
var compiledSelector = predicate.Compile();
return list.Select(x => string.IsNullOrWhiteSpace(compiledSelector(x)) ? "Not Available" : compiledSelector(x)).FirstOrDefault();
}
}
var name = MainList.GetFirstProperty(x => x.name);
var desc = MainList.GetFirstProperty(x => x.desc);
I assumed the data class. Use your own class as needed.
Upvotes: 1
Reputation: 10874
It makes no sense to use Linq in this way. The only collection-oriented operation in your code is the call to .FirstOrDefault()
. Simply do that, and then add a helper method for getting the fallback string if the input is null or empty, e.g.:
public static string GetPropertyWithFallback(Item item, Func<Item, string> getter) {
if (item != null) {
var val = getter(item);
if (!string.IsNullOrEmpty(val)) {
return val;
}
}
return "Not available";
}
public static void Main() {
var mainList = new List<Item>();
var firstItem = mainList.FirstOrDefault();
var name = GetPropertyWithFallback(firstItem, i => i.Name);
var descr = GetPropertyWithFallback(firstItem, i => i.Descr);
//etc.
}
Upvotes: 1
Reputation: 5201
I suggest you this approach:
var item = MainList.Select(x =>
new {
name = string.IsNullOrEmpty(x.name) ? "Not Available" : x.name,
//Same for other properties
}
).FirstOrDefault();
LC = item.name;
//Same for other properties
Upvotes: 1
Reputation: 42320
Note that your code has the perhaps slightly odd behaviour that if MainList
is empty, each of the final strings are all null
.
If this is intentional, you can add a helper function like this:
string ValueOrNotAvalable(MainListItem item, string value)
{
if (item == null)
return null;
return string.IsNullOrEmpty(value) ? "Not Available" : value;
}
var firstItem = MainList.FirstOrDefault();
LC = ValueOrNotAvalable(firstItem, firstItem?.name);
Description = ValueOrNotAvailable(firstItem, firstItem?.descr);
...
If you actually wanted to use the string "Not Available" if MainList
is empty, you can simplify it a bit:
string ValueOrNotAvailable(string value) => string.IsNullOrEmpty(value) ? "Not Available" : value;
var firstItem = MainList.FirstOrDefault();
LC = ValueOrNotAvalable(firstItem?.name);
Description = ValueOrNotAvailable(firstItem?.descr);
...
Upvotes: 2