Inline IF with no ELSE - c#

I'm trying to update the property of objects in a List based on a 0/1 pattern in a string.
//list.length is always == pattern.length
string pattern = Convert.ToString(8, 2);
var listWithDeleted = list.Select((s, index) => pattern[index] == '1' ? s.IsDeleted == true : s.IsDeleted = s.IsDeleted);
I'm a bit sad about the else-clause : s.IsDeleted = s.IsDeleted of my inlined if-statement. I understand inlined if needs an else-clause as it needs to return a value but it made me wonder if there may be a cleaner way to do this.

You can use:
s.IsDeleted = pattern[index] == '1' || s.IsDeleted
If it's already true, it will stay true regardless of pattern[index], otherwise it will only become true if pattern[index] is '1'

Here's another solution
s.IsDeleted = pattern[index] == '1' ? true : s.IsDeleted

Filter and only apply the operation where you need to. You wouldn't write the foreach equivalent in a ternary like that, so I don't see why you should do it that way in LINQ either.
list.Where((s, index) => pattern[index] == '1').Select(s => s.IsDeleted = true);
Note that it's strange to mutate in the Select (compounded by the strangeness of mutating in a ternary); in this case your listWithDeleted actually returns an IEnumerable<bool> (the result of the ternary) which seems odd. It would be better to use List.ForEach or your own void returning IEnumerable.ForEach extension to make intent a little clearer.

Related

Weird Lambda behavior in string equality

I have an array of strings obj[] values, but trying to use equality seems to be different than what I might expect, can someone clarify this?
content of values is ["train","train"];
var first = values.First();
values.Skip(1).All(v => Equals(v, first))
false
values.Skip(1).All(v => v.Equals(first))
true
Equals(values[0], values[1])
true
Equals(values[1], values[0])
true
values.Skip(1).All(v => Equals(v, first) == true)
false
values.Skip(1).Any(v => Equals(v, first) == false)
true
Any clue why it returns false?
Edit1: I have wrote a unit test and it passes, I'm checking if the strings have different cultures as #Michael Randall suggested
Equals implementation on MSDN
Your problem must be your input
Note : You should consider doing proper string comparison. Best Practices for Using Strings in .NET
However as you can see with the appropriate input, your code actually works
var first = "train";
var values = new object[]{"train", "train"};
Console.WriteLine(values.Skip(1).All(v => Equals(v, first)));
Console.WriteLine(values.Skip(1).All(v => v.Equals(first)));
Console.WriteLine(Equals(values[0], values[1]));
Console.WriteLine(Equals(values[1], values[0]));
Console.WriteLine(values.Skip(1).All(v => Equals(v, first) == true));
Console.WriteLine(values.Skip(1).Any(v => Equals(v, first) == false));
Output
True
True
True
True
True
False
You can test it here
#TheGeneral answer is usually the correct one, but in my case restarting the machine removed this issue. my guess it was the debugger have a bug.

Why does this handle not all conditions?

I am reading the answer to this question: (Is there a better way of calling LINQ Any + NOT All?). Why does this handle not all conditions? Sorry for creating a new question, but I don't have enough reputation to add a comment on the original question.
var anyButNotAll = mySequence
.Select(item => item.SomeStatus == SomeConst)
.Distinct()
.Take(2)
.Count() == 2;
If the condition is always false (or always true) then when projecting the sequence using the condition and calling Distinct there will be 1 result, not two, so Count() == 2 will return false, not true.

Checking for AND OR condition between two checks

Hi I have following linq statement
var list=(from c in db.sales
where c.id ==id && || c.name==name
select new model
{
//.....
});
I am having problem with my where clause.
Basically I can get id and name values or either one of them can be null. So I am trying to use where clause with AND OR meaning both condition could be right or either one.
With this where syntax i get intelliscence error. Please let me know how I can use AND OR check in the where clause.
both condition could be right or either one
You simply need or and do not need and
var list=(from c in db.sales
where c.id ==id || c.name==name
select new model
{
//.....
});
The || (or Operator)
The conditional-OR operator (||) performs a logical-OR of its bool
operands. If the first operand evaluates to true, the second operand
isn't evaluated. If the first operand evaluates to false, the second
operator determines whether the OR expression as a whole evaluates to
true or false, MSDN.
It sounds like what you want is just an ordinary OR:
where c.id == id || c.name == name
This will evaluate to true if c.id == id is true, if c.name == name is true, or if both are true.
I think you mean IntelliSense error. This is obvious, because && || is not valid C# syntax.
From what you describe, I think you only need the OR operation.
Try changing && || to just ||.

How to make AND operator in C# linq?

IEnumerable<WireUsrTgInfo> lstWireData =
(from var in lstWireUsrTgInfo
where var.bWireData == true && var.bWireData == false --> This is not working
select var).AsEnumerable<WireUsrTgInfo>();
How to do this ...
according to the code provided
var.bWireData == true && var.bWireData == false
it can not work, as the same variable can not contemporary be equal to both oposite values.
if you need parametrize this, you can do it like :
bool expectedValue = true; //OR False
IEnumerable<WireUsrTgInfo> lstWireData = (from var in lstWireUsrTgInfo
where var.bWireData == expectedValue
select var).AsEnumerable<WireUsrTgInfo>();
EDIT
And don't use var in the query, it's contextual (as mantioned by Monkieboy) C# keyword. To be clear: you can use it, but you have to avoid doing that as it creates confusion.
bWireData cannot both be true AND false. There's a flaw in your logic.
As other answers stated, your filter condition is wrong. But there is something else I want to add:
Don't compare boolean data with true or false. Boolean data is actually an answer to question is it true or not.
var query = from info in lstWireUsrTgInfo
where info.bWireData // selects data which is true
select info;
Also var is a keyword;
Also do not use prefixes in variable names (consider better naming instead - HasWireData, wireUserTagInfos).
This will never work: WHERE bWireData == true && bWireData == false is illogical be cause bWireData can't be both true and false at the same time.
var is a keyword and to avoid confusion should therefor not be used as a name for a variable.
&& is the correct operator. However, as other posters have noted, your query as it stands is equivalent to saying "Make me happy if Obama is president and Obama is not president". Basically you have set up a contradiction, which will always evaluate to false and thus return no results. As an aside, you may be interested to learn that && is a conditional-and, meaning that the second term is only evaluated if the first term is true, thus saving the processing of second term if the result is inevitably false anyway.

Possible to do this in linq?

I am wondering if something like this could be done(of course what I have written does not work but that's what I am essentially trying to achieve) .
var test = u.Owner;
a.Table.Where(u => test == true)
I have a linq query that I want to reuse(basically I got a query that I use 5 times) and the only thing that changes is what I am comparing against.
So in the above u.Owner is compared against true. In another query it would look the same but instead of u.Owner I might have u.Add == true or u.Edd == true.
So is there a way I can sort of reuse what I have. Of course in my code the query is a bit longer but I just shortened down.
Edit
Basically the whole query
List<Permission> clearence = user.PermissionLevels.Where(u => u.Id == Id &&( u.Add == permissionNeeded || u.Permission.Name == PermissionTypes.Owner)).ToList();
permissionNeeded == Enum
So my orignal way of doing it was u.Permission.Name == permissionNeeded so I compared the enum value to a string.
Now my db model has change and I need to check against 5 different permissions separately that are bools and not strings.
u.Add = true || u.Owner == true;
u.Edit = true || u.Owner == true;
u.Delete= true || u.Owner == true;
u.View= true || u.Owner == true;
Thats all changes for the entire query so that's why I am trying to make it into one query(just like I had it before).
So I am thinking of having a switch statement. The method still takes in a permissionNeeded(enum) I then go through and determine what clause I need and some how insert it into the query.
switch(PermssionNeeded)
{
case PermissionTypes.Add:
u.Add;
break;
// all other cases here.
}
Take advantage of the fact that Where can have any function taking type Table as a parameter and returning a boolean to create a function like:
public IQueryable<Table> QueryTables(Func<Table, bool> testFunction)
{
return a.Table.Where(testFunction).AsQueryable<Table>();
}
Edit: (in addition to edit to add AsQueryable above, which I earlier forgot)
If all you want to do is vary the boolean field used in the test, and you don't want to have to specify an entire function (which you're about to find out is much easier), you would need to use some reflection:
using System.Reflection;
public IQueryable<Table> QueryTables(PropertyInfo pi)
{
return a.Table.Where(t => (bool)(pi.GetGetMethod().Invoke(t, null))).AsQueryable<Table>();
}
To construct the PropertyInfo object, use something like:
PropertyInfo pi = typeof(Table).GetProperty("Owner");
I prefer the earlier method, but I did want to show that something like this is at least possible.
If you only want to specify the property you are checking you can do
public IEnumerable<Table> GetTables(Func<Table,bool> getValue)
{
return a.Table.Where(table => /*some common filter*/)
.Where(table => getValue(table))
}
var query = from u in uSrc join v in vSrc on u.ID equals v.RelatedUID
where v.Valid && u.Created < DateTime.UtcNow.AddDays(-365)
select u; // relatively complicated starting point.
var q1 = query.Where(u => u.Add); // must also have Add true
var q2 = query.Where(u => u.Test); // must also have Test true
var q3 = query.Where(u => u.ID < 50); // must also have ID < 50
And so on.
Edit:
Okay, so your starting query is:
List<Permission> clearence = student.PermissionLevels.Where(u => u.Id == Id &&( u.Add == permissionNeeded || u.Permission.Name == PermissionTypes.Owner)).ToList();
However, note that this creates a list, so any further work done on it will be a matter of Linq-to-objects. We'll come back to that in a minute, as it's sometimes good and sometimes not.
Now, if I understand you correctly, you need different sets for different cases, which you can do with your query as per:
var set0 = clearance.Where(u.Add = true || u.Owner == true);
var set1 = clearance.Where(u.Edit = true || u.Owner == true);
var set2 = clearance.Where(u.Delete= true || u.Owner == true);
var set3 = clearance.Where(u.View= true || u.Owner == true);
Now, this will work, but may not be the best approach. If we go back to the original query, we don't have to do ToList(), but can have:
IQueryable<Permission> clearence = student.PermissionLevels.Where(u => u.Id == Id &&( u.Add == permissionNeeded || u.Permission.Name == PermissionTypes.Owner));
Now, in the first case because we built a list we first got all values that matched the critera backed, and then stored it in memory, in clearance.
In the second case, clearance doesn't store any values at all, but instructions on how to get them.
The question is which is better to use. In the case where we are going to end up using the vast majority of the objects returned by the first query on its own, then there is a performance boost in using the list version, because they are loaded into memory only once, and then taken from memory without hitting the database again.
However, in most cases, it's better to do the second version for two reasons:
We hit the database in each case, but only retrieve the objects needed in that case.
We don't store anything in memory longer than necessary. Above a certain amount this is an important performance matter in itself.
The time to first item is faster this way.
We can further refine, for example if we do the following:
var trimmed = from set0 select new{u.Id, u.Permission.Name};
The we retrieve anonymous objects with Id and Name properties that are all we care about for a particular case, and not all of the relevant fields are retrieved from the database, or other source.
I've recently come to prefer a Dictionary over switch statements. You could store all your lambas in a Dictionary<PermissionNeeded, Func<User, bool>> that would look like this:
Dictionary<PermissionNeeded, Func<User, bool>> Permissions =
new Dictionary<PermissionNeeded, Func<User, bool>> {
{ PermissionNeeded.Add, u => u.Add }, // don't need to specify == true
{ PermissionNeeded.Edit, u => u.Edit },
...
etc
};
And you would call it like this:
var clearance = Permissions[PermissionNeeded.Add](user);
or maybe
var clearance = Permissions[PermissionNeeded.Add](user) && Permissions[PermissionNeeded.Edit](user);
or perhaps
var clearance = Permission[PermissionNeeded.Add](user) || Permissions[PermissionNeeded.View](user);
and so on. Even if you don't have a user object, I think this would still be valid and make the code pretty easy to read, and if you have to modify your functions, its all in the dictionary...

Categories