public bool IsNewUser(int id)
{
var data= DataContext.Employee.Where(e=>e.id==id).FirstorDefault();
if(data==null)
return true;
return false;
}
How can I write the above function logic using maybe ?? or something else in a single line in C#? I am sure that must be possible just can't think right now..Thanks
This wouldn't be a case to use ?? but this should help:
public bool IsNewUser(int id)
{
return !DataContext.Employee.Any(e => e.id == id);
}
?? would be used doing something like this:
public Employee GetEmployeeOrNew(int id)
{
return DataContext.Employee.Where(e => e.id == id).FirstorDefault() ?? new Employee();
}
return (null == DataContext.Employee.Where(e=>e.id==id).FirstorDefault());
The Any operator would be more appropriate than FirstOrDefault:
public bool IsNewUser(int id)
{
return !DataContext.Employee.Any(e => e.id == id);
}
return DataContext.Employee.Where(e=>e.id==id).FirstorDefault() == null;
?? is the null coalescing operator, used to assign a default value instead of null. IE
data = data ?? GetNonNullData();
?: is the ternary conditional, probably what you were thinking of. But it's not actually necessary in this case.
You should use the Any method instead of the Where...FirstOrDefault construct:
public bool IsNewUser(int id)
{
return !DataContext.Employee.Any(e=>e.id==id);
}
return !DataContext.Employee.Any(e=>e.id==id);
return data == null ? true : false;
return DataContext.Employee.Any(e => e.id == id);
Related
I am trying to use FirstOrDefault in my code but getting compile time error.
Cannot implicitly convert type Priority to bool
public class Priority
{
public string Name { get; set; }
public string Id { get; set; }
public string Default { get; set; }
}
public class ProcedureStatus
{
public string Id { get; set; }
public Priorities Priorities { get; set; }
}
public class Priorities
{
public List<Priority> Priority { get; set; }
}
foreach (Priority priority in status.Priorities.Priority)
{
if (priority.Default == "true" && grid.Priority == null)
{
grid.Priority = priority.Id;
grid.PriorityText = priority.Name;
SetPriority(gridRow);
break;
}
else if (status.Priorities.Priority.FirstOrDefault(x => x.Id == priority.Id))
priority.Default = "true";
}
How to use FirstOrDefault in my scenario.
You are using status.Priorities.Priority.FirstOrDefault(x => x.Id == priority.Id) in an if clause.
The if clause is expecting an expression that returns a bool, but your expression returns a Priority.
Aside from that, it looks like the if clause is redundant, since you are iterating the properties via a foreach and trying to get the current item from the list you are already iterating. If you just want to iterate the list, you don't need the if clause.
The way you would typically use FirstOrDefault would be like this:
var priority = status.Priorities.Priority.FirstOrDefault(x => x.Id == priorityId)`;
if (priority != null)
{
\\ ...
}
where priorityId is the ID of the priority you are looking for.
This does not seem useful inside you foreach loop though.
(Even after your question update, you still have the same if clause inside the foreach. It's just after an if/else now.)
The problem
The problem is not related to Lambda expressions (x => blablabla syntax) but related to what a specific function FirstOrDefault() returns and how to use it in an if-else-elseif scenario.
Analysis
The code you wrote could be written in two steps as:
if (priority.Default == "true" && grid.Priority == null)
{
// your if block
}
else
{
Priority firstPriority = status.Priorities.Priority.FirstOrDefault(x => x.Id == priority.Id);
// Same exact error you got... Cannot implicitly convert type Priority to bool
if (firstPriority) {
priority.Default = "true";
}
}
Now it is more easy to understand what the problem is... if, else and else if statements need a logical expression to work. That can be made either using a bool variable or doing a check/evaluation that returns true/false.
Solution
There are many different ways to address the problem:
You could use a function that directly returns a boolean like Any(), that would be useful if you do not need to use the object matching the x => x.Id == priority.Id.
You could use FirstOrDefault() but changing your else if to convert it into something that return a logic expression. This would be useful if you need to later work with that element.
Using the Any() function
else if (status.Priorities.Priority.Any(x => x.Id == priority.Id))
{
priority.Default = "true"; // Dumb question, why the Default property is not of type bool???
}
Using the FirstOrDefault()
Note: you have already been given this option in other answers. Ergwun's answer and Braulio's answer so far.
As per the documentation of the function I linked and what its name suggests, if the FirstOrDefault() function does not find anything, it returns null. So you could check it whatever it returns is null or not.
This could be done in a couple of ways. Depending on if you need to later work with whatever the function returns or not.
else if (status.Priorities.Priority.FirstOrDefault(x => x.Id == priority.Id) != null)
{
priority.Default = "true";
}
or
if (priority.Default == "true" && grid.Priority == null)
{
// your if block
}
else
{
Priority firstPriority = status.Priorities.Priority.FirstOrDefault(x => x.Id == priority.Id);
if (firstPriority != null) {
priority.Default = "true";
Console.WriteLine("The description of the priority if the Id XXXX is: " + firstPriority.Description);
}
}
Best way it's to compare if your object is not null after the research
foreach (Priority priority in status.Priorities.Priority)
{
if (grid.Priority == null)
{
grid.Priority = priority.Id;
grid.PriorityText = priority.Name;
break;
}
else if (status.Priorities.Priority.FirstOrDefault(x => x.Id == priority.Id) != null)
// You found something, do this.
}
Try it
I want to use the null-coalescing operator with three Statements.
If the first list returns null then return the second list
If second list returns null then return the third list
private IList<a> a => new IList<a>().ToList();
private IList<a> CalcDate
{
get
{
return a.Where(p => p.a.LastDate.HasValue && p.a.LastDateHasValue <= DateTime.Today)
?? a.Where(p => p.LastUpdateDate.HasValue && p.LastUpdateDate <= DateTime.Today)
?? a.Where(p => p.CreateDate.HasValue && p.CreateDate <= DateTime.Today);
}
}
I don't want to use ?: operator, because I want to keep the code short.
Please help me with ideas for short and readable code and more tips
You can add your own extension method called NullIfEmpty like following
public static class Extensions
{
public static IEnumerable<T> NullIfEmpty<T>(this IEnumerable<T> seq)
{
if (!seq.Any())
return null;
return seq;
}
}
And then you can use this method somewhat like this:
return a.Where(...).NullIfEmpty()
?? a.Where(...).NullIfEmpty()
?? a.Where(...);
I have a property that executes a LINQ query. Why does it return a bool? How can I make it return an instance of my ORMClass?
public string ContactPersonName
{
get
{
return Convert.ToString(
Client.ContactPersons.Select(x => x.MainContactPerson == true).First()
);
}
}
I want some of
((ContactPerson)Client.ContactPersons.Select(x => x.MainContactPerson == true).First())).Name //typecast error
You should use Where to filter instead of Select
Client.ContactPersons.Where(x => x.MainContactPerson).First();
For simpler:
Client.ContactPersons.First(x => x.MainContactPerson);
You're doing a Select when you really want a Where
public string ContactPersonName
{
get
{
return Convert.ToString(
(
Client.ContactPersons.Where(x => x.MainContactPerson == true).First())
)
;
}
}
I have this simple method:
#region Fields
private Collection<Address> _addresses;
#endregion
#region Public methods
public Address DeliveryAddress()
{
if (_addresses == null)
if (this.Id > 0)
_addresses = Core.Data.Addresses.GetClient(this.Id);
return _addresses.SingleOrDefault(x => x.TypeId == AddressType.Delivery);
}
public Address InvoiceAddress()
{
if (_addresses == null)
if (this.Id > 0)
_addresses = Core.Data.Addresses.GetClient(this.Id);
return _addresses.SingleOrDefault(x => x.TypeId == AddressType.Invoice);
}
#endregion
As you can see I trying to return one result for a DeliveryAddress and one result for an InvoiceAddress. My problem is that I would like the link expression to create a new instance of Address() if SingleOrDefault returns null.
I am really new to linq, so I am not sure whether SingleOrDefault is the correct expression I should be using.
You could use DefaultIfEmpty and use that instance as default value:
return _addresses.Where(x => x.TypeId == AddressType.Delivery)
.DefaultIfEmpty(new Adress())
.Single();
Use the null-coalescing operator:
return _addresses
.SingleOrDefault(x => x.TypeId == AddressType.Delivery) ?? new Address();
The expression
x ?? y
yields x if x is not null, otherwise y. You can chain the operator
x ?? y ?? z ?? t
This returns the first non-null value or null if all of them are null.
UPDATE
Note that SingleOrDefault throws an exception if the sequence has more than one element. If you need the first element of a sequence possibly having no or more than one element, use FirstOrDefault instead.
You could create your own extension method, like this:
public static T NewIfNull<T>(this T obj) where T: class, new()
{
return obj ?? new T();
}
... then tack a usage onto the end of SingleOrDefault:
var singleResult = myCollection.SingleOrDefault().NewIfNull();
... or because the logic is so simple, just inline it as other answers have said.
Instead of
return _addresses.SingleOrDefault(x => x.TypeId == AddressType.Delivery);
Do something like this:
var address = _addresses.SingleOrDefault(x => x.TypeId == AddressType.Delivery);
if(address == null)
address = new Address();
return address;
I'd be inclined to write both of these as extension methods on IEnumerable<Address>. You can use the null-coalesing operator to return a new instance if the SingleOrDefault() call returns null.
public static class AddressExtensions
{
public static Address DeliveryAddress(this IEnumerable<Address> addresses)
{
return addresses.SingleOrDefault(x => x.TypeId == AddressType.Delivery)
?? new Address();
}
public static Address InvoiceAddress(this IEnumerable<Address> addresses)
{
return addresses.SingleOrDefault(x => x.TypeId == AddressType.Invoice)
?? new Address();
}
}
Apart from alternatives in other answers, you can also create your own SingleOrNew Extension method.
public static TSource SingleOrNew<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate ) where T:new()
{
return source.SingleOrDefault(predicate) ?? new T();
}
It can be used as
return _addresses.SingleOrNew(x => x.TypeId == AddressType.Delivery);
The following overloaded ==operator is part of the Calender class in QL.net
public static bool operator ==(Calendar c1, Calendar c2)
{
return (c1.empty() && c2.empty())
|| (!c1.empty() && !c2.empty() && c1.name() == c2.name());
}
public bool empty() { return (object)calendar == null; }
When I try to access the SouthAfricanCalender property, I receive a System.NullReferenceException : Object reference not set to an instance of an object. which prompted me to dig into the source.
public SouthAfrica SouthAfricanCalender
{
get
{
if (_calender == null)
{
_calender = new SouthAfrica();
}
return _calender;
}
set
{
if (_calender == null)
{
_calender = value;
}
}
}
SouthAfrica _calender;
I have ammended the overload as follows based on the answer here
public static bool operator ==(Calendar c1, Calendar c2)
{
if ( object.ReferenceEquals(c1,c2)) return true;
if ((object)c1 == null || (object)c2 == null) return false;
return (c1.empty() && c2.empty())
|| (!c1.empty() && !c2.empty() && c1.name() == c2.name());
}
My question, have I changed the intent of the original code with my amendment?
Edit: any suggestions on how this can be cleaned up further?
No. You ensure that both are objects, and respond accordingly in the places that they aren't (assuming that ReferenceEquals can handle double null). Then you simply execute the same check. The whole .empty() thing is totally unnecessary, by the way, you already know that it's not null, just return the name comparison.
No, you haven't.
It still checks for equality.