Ahh, don't you just love a good ternary abuse? :) Consider the following expression:
true ? true : true ? false : false
For those of you who are now utterly perplexed, I can tell you that this evaluates to true. In other words, it's equivalent to this:
true ? true : (true ? false : false)
But is this reliable? Can I be certain that under some circumstances it won't come to this:
(true ? true : true) ? false : false
Some might say - well, just add parenthesis then or don't use it altogether - after all, it's a well known fact that ternary operators are evil!
Sure they are, but there are some circumstances when they actually make sense. For the curious ones - I'm wring code that compares two objects by a series of properties. It would be pretty nice if I cold write it like this:
obj1.Prop1 != obj2.Prop1 ? obj1.Prop1.CompareTo(obj2.Prop1) :
obj1.Prop2 != obj2.Prop2 ? obj1.Prop2.CompareTo(obj2.Prop2) :
obj1.Prop3 != obj2.Prop3 ? obj1.Prop3.CompareTo(obj2.Prop3) :
obj1.Prop4.CompareTo(obj2.Prop4)
Clear and concise. But it does depend on the ternary operator associativity working like in the first case. Parenthesis would just make spaghetti out of it.
So - is this specified anywhere? I couldn't find it.
Yes, you can rely on this (not only in C# but in all (that I know) other languages (except PHP … go figure) with a conditional operator) and your use-case is actually a pretty common practice although some people abhor it.
The relevant section in ECMA-334 (the C# standard) is 14.13 §3:
The conditional operator is right-associative, meaning that operations are grouped from right to left.
[Example: An expression of the form a ? b : c ? d : e is evaluated as a ? b : (c ? d : e). end
example]
If you have to ask, don't. Anyone reading your code will just have to go through the same process you did, over and over again, any time that code needs to be looked at. Debugging such code is not fun. Eventually it'll just be changed to use parentheses anyway.
Re: "Try to write the whole thing WITH parentheses."
result = (obj1.Prop1 != obj2.Prop1 ? obj1.Prop1.CompareTo(obj2.Prop1) :
(obj1.Prop2 != obj2.Prop2 ? obj1.Prop2.CompareTo(obj2.Prop2) :
(obj1.Prop3 != obj2.Prop3 ? obj1.Prop3.CompareTo(obj2.Prop3) :
obj1.Prop4.CompareTo(obj2.Prop4))))
Clarification:
"If you have to ask, don't."
"Anyone reading your code..."
Following the conventions common in a project is how you maintain consistency, which improves readability. It would be a fool's errand to think you can write code readable to everyone—including those who don't even know the language!
Maintaining consistency within a project, however, is a useful goal, and not following a project's accepted conventions leads to debate that detracts from solving the real problem. Those reading your code are expected to be aware of the common and accepted conventions used in the project, and are even likely to be someone else working directly on it. If they don't know them, then they are expected to be learning them and should know where to turn for help.
That said—if using ternary expressions without parentheses is a common and accepted convention in your project, then use it, by all means! That you had to ask indicates that it isn't common or accepted in your project. If you want to change the conventions in your project, then do the obviously unambiguous, mark it down as something to discuss with other project members, and move on. Here that means using parentheses or using if-else.
A final point to ponder, if some of your code seems clever to you:
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. — Brian W. Kernighan
The assertion that parentheses detract from the readability of the code is a false assumption. I find the parenthetical expression much more clear. Personally, I would use the parentheses and/or reformat over several lines to improve readability. Reformatting over several lines and using indenting can even obviate the need for parentheses. And, yes, you can rely on the fact that the order of association is deterministic, right to left. This allows the expression to evaluate left to right in the expected fashion.
obj1.Prop1 != obj2.Prop1
? obj1.Prop1.CompareTo(obj2.Prop1)
: obj1.Prop2 != obj2.Prop2
? obj1.Prop2.CompareTo(obj2.Prop2)
: obj1.Prop3 != obj2.Prop3
? obj1.Prop3.CompareTo(obj2.Prop3)
: obj1.Prop4.CompareTo(obj2.Prop4);
x = cond1 ? result1
: cond2 ? result2
: cond3 ? result3
: defaultResult;
vs
if (cond1) x = result1;
else if (cond2) x = result2;
else if (cond3) x = result3;
else x = defaultResult;
I like the first one.
Yes, you can rely on conditional operator associativity. Its in the manual, at the link kindly provided by dcp, stated as "The conditional operator is right-associative", with an example. And, as you suggested and I and others agreed, the fact that you can rely on it allows clearer code.
Refer to msdn:
http://msdn.microsoft.com/en-us/library/ty67wk28%28VS.80%29.aspx
"If condition is true, first expression is evaluated and becomes the result; if false, the second expression is evaluated and becomes the result. Only one of two expressions is ever evaluated."
Related
This is just a wondering question for the c# language. I have checked in the MSDN operators and can't see anything close.
When I use LINQ to XML to retrieve some elements, I am passing some lambda expressions in WHERE methods to select specific elements.
But I can see that I am using the following statement which annoys me a bit.
bool myCondition;
// some codes
var elements = xDocument.Descendants("items").
Where(x=>x.Attribute("id")!=null&&
(myCondition)x.Element("blah").Value=="blah":
x.Element("blah").Value!="blah").ToList();
But somehow I keep writing to code as below(no idea why :)):
// some codes
var elements = xDocument.Descendants("items").
Where(x=>x.Attribute("id")!=null&&
x.Element("blah").Value?myCondition="blah").ToList();
I kind of see the boolean myCondition as !(exclamation mark) or =(equal sign).
if true then = if false then !.
I just wonder would that be any possibility in the future to add these types of operators? or there are some better operators that would shorten my condition?
Would this work with any other programming language out there? maybe javascript?
and if you are downgrading then please tell why.
You can already express that condition in C# without conditional operator:
myCondition?
xDocument.Element("item").Value=="blah":
xDocument.Element("item").Value!="blah"
is the same as:
myCondition == (xDocument.Element("item").Value == "blah")
Whether it is more readable is open question. You may consider having helper method with good name instead.
Currently I'm refactoring my old code, so I have some time to think about how code should look like for somebody else. I managed much of problems, but I always wonder how to prepare good syntax for some nested logical condition. Let's assume that we have following part of code:
bool param1;
int param2;
var result = ( param1 == toCheck.param1) && // to achive condition it always has to be true
((param2 == toCheck.param2)) ||
( (!param1) &&
(param2 == defaultValueForParam2));
// to pass condition param! has to be always true AND ( (params 2 has to be equal) OR (param1 has to be false AND param2 has to be equal with default value)
How should it be formated to be more readable for anybody? Are there some rules of formating conditions? Maybe the general solution is just wrong if I need so complicated condition?
My intention was to ask about: how I should use brackets, how I should use indents, grouping, etc?
If you have a complicated condition, that you cannot make less complicated, it helps to
Have good variable names
Write a small helper function with a clear name so that the calling code is clear
If the conition is used in more that one place Don't Repeat Yourself (see 2.)
Reconsider if you can simplify this. Do you really need boolean flags?
I'm reading an source code, I found a statement like this:
if (Char.IsWhiteSpace(text[i]) | GetSpecialChars.Contains(text[i]))
Initially,I thought it was typo,instead || (or) operator. But for my surprise, it was compiled. how to it's possible? is | equivalent to || with boolean types?
Thanks in advance.
I'd suggest that it probably is a typo, though it will still work.
The reason boolean | is so rarely seen is that:
Much of the time || is the only one that is correct. If the expression on the right hand side would throw if the expression on the left-hand was true such as in x == null || x.Length == 0 which would successfully return true for a null or zero-length string or array while x == null | x.Length == 0 which would throw an exception for a null string or array as the Length property would still be examined.
Most of the rest of the time || will be faster. It might be nothing but a couple of clock cycles faster (though it could also be more if the expression on the rhs is expensive), but it hardly counts as a premature optimisation that we're all in the habit of using that form. (Just how much effort you put into deciding which goes on the left and which on the right may be another matter).
Some constructs that use it by one-line fans are rather unclear as far as readabilty goes.
The example in the question falls under point two. The only effect of | rather than || here in practice is a few nanoseconds of waste. Not that it matters, but it does lead to || being the habit to fall into.
(If on the other hand a property called GetSpecialChars or a method called Contains has a side-effect that means it has to be called, that property really needs to be renamed to make it clearer!).
About the only time it's useful is either because we really need some side-effect of the right-hand expression to take place, or in the assignment form based on it, |=.
In the former case, it's always worth considering an alternative of evaluating both expressions in separate statements and then ORing the result afterwards, to make it clearer that you care about the side-effect as well as the result.
In the latter case, it can make for more readable code, or at least to code that's more readable to some people! But many find it obscures things.
|| is the short-circuiting version of |. In your if statement, the GetSpecialChars.Contains method will be executed even if the character is white space, whereas || would halt evaluation and not execute the right side.
There is no mistake, this is a boolean OR operator, as opposed to the OR ELSE operator represented by ||. The difference is that the regular OR does not short-circuit, while OR ELSE does.
In your specific case, GetSpecialChars.Contains(text[i]) will be called even if Char.IsWhiteSpace(text[i]) returns true. If you replace | with ||, this would no longer happen (i.e. GetSpecialChars.Contains(text[i]) will not get called if Char.IsWhiteSpace(text[i]) is true).
The | operator in general has two meanings as used with integrals and used with booleans. In the first case it calculates the bit-wise OR of the integrals whereas in the latter case it calculates the logical OR when used with boolean values.
The second case (the logical-OR case) brings another two meanings:
"|" calculates the logical OR with the restriction that it evaluates both values i.e. x | y == false if and only if both x and y are false.
"||" does the same thing but only evaluates the second operand if necessary. So in the former example x || y would evaluate to true as soon as x is evaluated to true without looking at y.
You can refer directly to the MSDN documentation for that here and here
Hope this helps.
I assume this should be fine
bool prefMatch = false;
// Is the frequency the same?
prefMatch = string.Compare(user.Frequency, pref.Action.ToString()) == 0;
so if user.Frequency is "3" and pref.Action.ToString() is "3" then it should set the prefMatch to true right? I'm getting false and I've definitely checked the 2 values in the watch tab in VS 2008 just to be sure they're the same
You can just use ==
prefMath = (user.Frequency == pref.Action.ToString());
Though string.Compare will also work. I suggest there is a problem elsewhere.
-- Edit
Also, just for completeness, there is no point assigning a variable to something, and then assigning it again directly after. It's slightly confusing to do so, so better to leave it unassigned, or assign it all in one spot. This way the compiler can help you if you have a case where it doesn't get assigned like you think. It is, obviously, acceptable to assign first if you wrap the second assignment in a try/catch though.
In situations like these, it's sometimes tempting to point the finger of blame at third-party code, as you've done here. Sometimes, this is justified - but not here. String.Compare is a central, extremely-well-tested piece of the .NET Framework. It's not failing. I guarantee it.
What I find helpful in these situations is to isolate the failure. Write a small, self-contained test case that attempts to demonstrate the problem. Write it with as few dependencies as possible. Make it a stand-alone console application, if possible. Post it here. If we can take it, compile and run it, and reproduce the problem, we can help you. I'd bet money, though, that in the course of creating this test case, you'll experience a head-slapping moment - "of course!" - and realize what the problem is.
Maybe the string(s) contain unprintable characters ?
To check, I'd do something like :
byte[] b1 = System.Text.Encoding.UTF8.GetBytes(user.Frequency);
byte[] b2 = System.Text.Encoding.UTF8.GetBytes(pref.Action.ToString());
then compare the contents of b1 and b2.
Of these two options:
var result = from c in coll where c % 2 == 0 select c;
var result = coll.Where ( c => c % 2 == 0 );
Which is preferable?
Is there any advantage to using one over the other? To me the second one looks better, but I would like to hear other people's opinions.
If you've only got one or two clauses, I'd go for "dot notation". When you start doing joins, groupings, or anything else that introduces transparent identifiers, query syntax starts to appeal a lot more.
It's often worth trying it both ways and seeing what's the most readable for that particular situation.
In terms of the generated code, they'll be exactly the same in most cases. Occasionally there'll be an overload you can use in dot notation which makes it simpler than the query expression syntax, but value readability over everything else in most cases.
I also have a blog post on this topic. I would definitely recommend that developers should be comfortable with both options - I'd be quite concerned if a colleague were using LINQ but didn't understand the fundamentals of what query expressions were about, for example. (They don't need to know every translation involved, but some idea of what's going on will make their lives a lot easier.)
I always use the lambda syntax because to me it's clearer what's actually happening and it looks cool to boot. But we have some devs here that always do the opposite (sql nerds I guess :) Fortunately, tools like ReSharper can just transform between the two with a click.