I have a method returning IEnumerable object, but I found that sometimes (on error) the method returns null value of IEnumerable.
The method looks something like this.
IEnumerable<string> function(String param1, String param2)
{
IEnumerable s = null;
s = (some query over here);
return s;
}
When I call this method with param2, the function internally fails and returns s which is null at this time.
So, to detect this I used,
IEnumerable<string> a = function(1,0);
if (a.count<string> > 0) //not working
if (a == 0) //not working.
What is the correct method to use IEnumerable and check whether it is null before any other operation?
you could return an empty enumerable if the search result was null:
IEnumerable<string> function(String param1, String param2)
{
IEnumerable s = null;
s = (some query over here);
return s ?? Enumerable.Empty<string>();
}
Yours s = (some query over here); is returning null. That is why you are getting the exception.
Later your check should be:
if(a != null)
and
if(a.Count() > 0)
You can combine both as:
if(a!=null && a.Count() >0)
{
// do your work
}
null is not the same as an enumeration without any elements. Therefore, your check for if(a.count<string> > 0) fails. (In fact, a isn't pointing to any instance whose number of elements you could retrieve with Count.)
Also, null is not the same as the integer value 0. Therefore, your check for if(a == 0) fails, too.
However, null is a keyword in C# and you can compare to that:
if (a == null)
Related
Assume I have a list of binary parameters (in reality it is a list of checkboxes' IsChecked.Value property). I'm trying to get the bool? (ternary) result that:
is true if all the elements in the list are true
is false if all the elements in the list are false
is null in all other cases, thus there are both true and false elements in the list or the list is empty
Until now I came up with the solution that requires iterating over the list twice (checking whether all elements are either true or false) and then comparing the results to deciding whether to return true, false or null.
This is my code:
bool checkTrue = myListOfBooleans.All(l => l);
bool checkFalse = myListOfBooleans.All(l => !l);
bool? result = (!checkTrue && !checkFalse) ? null : (bool?)checkTrue;
How can I achieve it in only one iteration over the list?
You could do that by using Aggegrate
public bool? AllSameValue(List<bool> myListOfBooleans)
{
if(myListOfBooleans.Count == 0) return null; // or whatever value makes sense
return myListOfBooleans.Cast<bool?>().Aggregate((c, a) => c == a ? a : null);
}
That casts your values to bool? so that you can then compare them and return the value if that they all match or null if there is a difference.
Of course you could exit early by taking the first one and using All to see if the rest match or not.
public bool? AllSameValue(List<bool> myListOfBooleans)
{
if(myListOfBooleans.Count == 0) return null; // or whatever value makes sense
bool first = myListOfBooleans[0];
return myListOfBooleans.All(x => x == first ) ? first : null;
}
You can simply count the true values:
int c = myListOfBooleans.Count(l => l);
bool? result = c == myListOfBooleans.Count
? (bool?)true
: (c == 0 ? (bool?)false : null);
Note that this is true for an empty list, you may want to tweak that according to your required logic.
For a better performance (though I don't think it matters in a UI context) you could write an extension that could even return early if the result is clear (instead of iterating through the whole list):
public static bool? AllOrNothing(this IEnumerable<bool> list)
{
if (list == null) throw new ArgumentNullException(nameof(list));
using(var enumerator = list.GetEnumerator())
{
if (!enumerator.MoveNext())
return null; // or true or false, what you need for an empty list
bool? current = enumerator.Current;
while(enumerator.MoveNext())
if (current != enumerator.Current) return null;
return current;
}
}
And use it:
bool? result = myListOfBooleans.AllOrNothing();
return ship.DefenseType?.PropulsionMethod != null
? new BattleMethod(ship.DefenseType.PropulsionMethod)
: null;
Hi, my current return statement, above, is returning a Propulsion method if it's not null. However, my database has different types of
propulsion methods denoted by the first 2 letters in the field(PK, PA, PT, etc).
How can I check to make sure that the PropulsionMethod starts with "PK" before going further into the return statement?
In pseudo code, it might look something like this:
if (ship.DefenseType?.PropulsionMethod).startsWith("PK")
&& ship.DefenseType?.PropulsionMethod != null)
{
return new BattleMethod(ship.DefenseType.PropulsionMethod)
}
else
{
return null;
}
I tried
return ship.DefenseType?.PropulsionMethod != null &&
ship.DefenseType?.PropulsionMethod.StartsWith("PK")
? new BattleMethod(ship.DefenseType.PropulsionMethod)
: null;
But I get this error:
operator && cannot be applied to operands of type bool and bool?
Just add this condition too:
return ship.DefenseType?.PropulsionMethod != null
&& ship.DefenseType?.PropulsionMethod.StartsWith("PK")
? new BattleMethod(ship.DefenseType.PropulsionMethod) : null;
As the operator is && so the second condition will be evaluated if the first one was true (not null in this case).
You can compare nullable bool directly with true:
return ship.DefenseType?.PropulsionMethod?.StartsWith("PK") == true
? new BattleMethod(ship.DefenseType.PropulsionMethod)
: null;
I have a linq query in which i am getting the user list and after that we are getting the record by userid filter.
var user = UserDal.GetAllUsers().First(n => n.UsersID == 1);
But what should do if GetAllUsers() function returns null ? Should we check it by applying Any() ? Or something else ?
But what should do if GetAllUsers() function returns null ?
If UserDal.GetAllUsers returns null, then you can't use Any, you will have to check it against null. You can only use Any or FirstOrDefault if the method returns a collection (even empty).
If the method could return null then:
var temp = UserDal.GetAllUsers();
if(temp != null)
{
var user = temp.FirstOrDefault(n=> n.UserID == 1);
}
If your method could return an empty collection instead of null then you can do:
var user = UserDal.GetAllUsers().FirstOrDefault(n => n.UsersID == 1);
You should modify your method UserDal.GetAllUsers to not return a null. If there are no records then an empty collection should be returned.
Why not simply check if it is null?
var users = UserDal.GetAllUsers();
if (users == null || !users.Any())
{
// handle error
}
var user = users.First(x => x.Id == someId);
However, if you're in control of the code-base, I'd certainly say that you should make it so GetAllUsers never returns null.
You could use [DefaultIfEmpty] and use that instance as default value: to handle null value
You could use Monads, e.g. https://github.com/sergun/monads.net
Or you could implement your own extension methods.
This code is adapted from the original extension method and returns default(T) instead of throwing an exception.
// UserDal.GetAllUsers() returns null and user is null
var user = UserDal.GetAllUsers().MyFirstOrDefault(n => n.UsersID == 1);
public static class IEnumerableExtensions
{
public static T MyFirstOrDefault<T>(this IEnumerable<T> source,
Func<T, bool> predicate)
{
if (source == null) return default(T);
if (predicate == null) return default(T);
foreach (T element in source)
{
if (predicate(element)) return element;
}
return default(T);
}
}
Or you could use null checks or ensure never to return null to safeguard against null reference exception when using the standard extension methods.
I'm working with the new Task Parallel Library and today went to this case:
This code doesn't compile:
internal Task<Guid?> SavePages(string[] pages)
{
return Task.Run(() =>
{
if (pages == null || pages.Length == 0)
return null;
....
Unless I explicitly returns a null nullable Guid:
internal Task<Guid?> SavePages(string[] pages)
{
return Task.Run(() =>
{
if (pages == null || pages.Length == 0)
return (Guid?)null;
// Check documents path access
Why this behavior, I'm I doing something wrong? I mean, I get the code to work with the second option but don't know If I'm misusing the library, I mean, null is always null, isn't it?
Compile error:
Cannot convert lambda expression to delegate type
'System.Func' because some of the return
types in the block are not implicitly convertible to the delegate
return type
http://msdn.microsoft.com/en-us/library/dd460717.aspx
This has to do with the way the compiler determines the type of your lambda. When you return a plain null, the only thing the compiler can imply is that you are returning an object. Hence, your parameterless lambda is compatible with Task<object>. However, the signature of your function says that you are returning Task<Guid?>, so the return type the compiler implied from your code is not compatible. When you cast that null to Guid?, you provide the compiler a the clue it is missing to make the lambda a Task<Guid?>.
This is a limitation with type inference in the C# compiler. This issue is not unrelated to the one involving the ternary operator:
int? num = a != null ? a.Value : null; // Will not compile
int? num = a != null ? a.Value : (int?)null; // Compiles
int? num = a != null ? (int?)a.Value : null; // Compiles
Another workaround for your specific situation is to specify the generic type explicitly:
return Task.Run<Guid?>(() =>
{
if (pages == null || pages.Length == 0)
return null;
I am trying to return a Guid value below. However the database(and my dbml) has that column as a nullable Guid and it is generating an exception on the .Select portion saying it can't convert from an IQueryable<System.Guid?> to a System.Guid.
I am guessing I need to make my return value "concrete" first???? True?
If so how do I do that with Guid's?
public static Guid GetCurrentWorkerByType(int enrollmentID, int staffTypeID)
{
using (var context = CmoDataContext.Create())
{
IQueryable<tblWorkerHistory> tWorkHist = context.GetTable<tblWorkerHistory>();
return (tWorkHist.Where(workHist =>
(workHist.EnrollmentID == enrollmentID) &&
(workHist.tblStaff.StaffTypeID == staffTypeID) &&
(workHist.EndDate == null || workHist.EndDate > DateTime.Now))
.Select(workHist => workHist.Worker));
}
}
}
// Get the Guid? itself, for sake of example from IQueryable<Guid?>
// (could be `null` from DB value or because queryable was empty)
Guid? maybeGuid = queryable.FirstOrDefault();
// Need to have *a* GUID or default it to something
// because a Guid is a value-type and needs *a* value.
Guid theGuid = maybeGuid ?? Guid.Empty;
Also see Nullable<T>.HasValue/Value -- A longer, but equivalent, method would be:
Guid theGuid = maybeGuid.HasValue ? maybeGuid.Value : Guid.Empty;
Observe that HasValue may be suitable in general if statements to change logic and also note that Value will throw an exception if maybeGuid is "has no value" -- is null -- which is why the guard is required.
Happy coding.
Pedantic detail: The equivalent method is not "thread safe". That is, assuming maybeGuid was shared, it could be assigned null between HasValue and Value. There are a number of SO questions that cover the "thread safety" of ?? (the coalesce operator) -- the generated IL effectively uses a temporary variable so the value may be stale but an exception can't be thrown.
Use
.Select(workHist => workHist.Worker).Single();
.Select() returns a query that has not run.
If you use .Select().ToList() then you you return a list.
If you use .Select().Single() then you return one item and it makes sure only one item is there
If you use .Select().SingleOrDefault() then you return one item and default. Query must not contain more than 1 item.
If you use .Select().First() then you return the first item. Query must contain at least 1 item.
If you use .Select().FirstOrDefault() then you return the first item or default. Query can contain 1 or more or no items.
Try
Change your return type from System.Guid to ?System.Guid // nullable of guid
Then add .FirstOrDefault() after the select call
A struct cannot be null, but the System.Nullable class wraps the struct in a class.
What you've got is a query that hasn't executed for one, and for two, it will return a list of Guids as far as I can tell. If you want to return the first Guid or default (which I believe is a zero'd out guid) you can say .FirstorDefault() after your select.
The closest you will get representing null with a Guid is to use Guid.Empty. So, for your query, you will probably want to first pick the value returned by FirstOrDefault, make a null check, and then return a reasnable value:
Guid? result = tWorkHist.Where(workHist =>
(workHist.EnrollmentID == enrollmentID)
&& (workHist.tblStaff.StaffTypeID == staffTypeID)
&& (workHist.EndDate == null || workHist.EndDate > DateTime.Now))
.Select(workHist => workHist.Worker)
.FirstOrDefault();
return result.HasValue ? result.Value : Guid.Empty;
Use FirstOrDefault with conjunticon with Guid.Empty
Try this:
public static Guid GetCurrentWorkerByType(int enrollmentID, int staffTypeID)
{
using (var context = CmoDataContext.Create())
{
IQueryable<tblWorkerHistory> tWorkHist = context.GetTable<tblWorkerHistory>();
var guid = (tWorkHist.Where(workHist => (workHist.EnrollmentID == enrollmentID) &&
(workHist.tblStaff.StaffTypeID == staffTypeID) &&(workHist.EndDate == null || workHist.EndDate > DateTime.Now))
.Select(workHist => workHist.Worker)
///####NOTICE THE USE OF FirstOrDefault
).FirstOrDefault();
return (guid.HasValue)?guid.Value:Guid.Empty
}
}