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.
Related
I'm having a difficult time trying to figure out how to provide certain functionality required for a business application I'm working on.
Basically, we have a string in the DB that contains a conditional statement such as
"(("SomeString.Contains("XYZ") AND SomeString.Contains("VBN")) OR SomeString.Contains("ABC"))"
(This string could contain tons of conditional statements, this is just a simple example).
What I am asked to do is pull that string in from the DB and insert it into an If statement to determine whether or not "SomeString" meets those requirements. "SomeString" will just be a specific string that I will replace once the code is run.
The end result in my mind would be as follows...
if (((SomeString.Contains("XYZ") && SomeString.Contains("VBN")) || SomeString.Contains("ABC")) {
return true;
}
The problem lies in the fact that even if I parse the "AND"s and "OR"s into their code form of "&&"s and "||"s, the value entered into the if statment is still of type string which means the statement will not be treated as a conditional statement.
Is there any way to do this in C#? Libraries or otherwise.
I'm not necessarily looking for someone to write the code for me, I just need a push in the right direction.
Thank you!
I want to perform an AND operation. My inputs are 2 objects. It could be a string like "true" or it could be an expression like "1==1" as well. When using && operator, am getting an exception that String was not recognized as a valid boolean.
Please help me.
return Convert.ToBoolean(obj[0]) && Convert.ToBoolean(obj[1]);
Sorry for the earlier post which was not clear enough.
Converting "1==1" to a boolean is not possible for the Convert.ToBoolean method. It just converts the strings true and false.
You will have to either write a expression evaluator yourself, or use some kind of library to parse your string to a boolean (like Flee for example)
First make sure obj[0], obj[1] will only contain 1 or 0(char or integer).
Because Convert.ToBoolean does not understand anything other than 1 or 0.
The below one will work
Convert.ToBoolean(true) && Convert.ToBoolean(1==1)
Why use a string?
The conversion will not evaluate code, it will check if the supplied data is possible to convert to a bool and do so if possible.
Your function will always return true if it was working, cause 1 is always equal to 1, and true is always true.
This is nearly impossible as C# is strongly type language.
What you trying to do is for weakly types languages like JS. "1==1" will work for JS, not for C#.
Remove quotes in order to make it work(You might as well remove first operand, as it doesn't make any sense):
return ( 1 == 1 );
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 am validating input on a form and attempting to prompt the user of improper input(s) based on the combination of controls used.
For example, I have 2 combo boxes and 3 text boxes. The 2 combo boxes must always have a value other than the first (default) value, but one of three, or two of three, or all text boxes can be filled to make the form valid.
In one such scenario I have a 6 line if statement to try to make the test easily readable:
if ((!String.Equals(ComboBoxA.SelectedValue.ToString(), DEFAULT_COMBO_A_CHOICE.ToString())
&& !String.IsNullOrEmpty(TextBoxA.Text)
&& !String.Equals(ComboBoxB.SelectedValue.ToString(), DEFAULT_COMBO_B_CHOICE.ToString()))
||
(!String.IsNullOrEmpty(TextBoxB.Text)
|| !String.IsNullOrEmpty(TextBoxC.Text)))
{
//Do Some Validation
}
I have 2 questions:
Should this type of if statement be avoided at all cost?
Would it be better to enclose this test in another method? (This would be a good choice as this validation will happen in more than one scenario)
Thanks for your input(s)!
In such a case I find it helps to move some of the logic out of the if statement and into some more meaningfully named booleans. Eg.
bool comboBoxASelected = !String.Equals(ComboBoxA.SelectedValue.ToString(), DEFAULT_COMBO_A_CHOICE.ToString());
bool comboBSelected = !String.Equals(ComboBoxB.SelectedValue.ToString(), DEFAULT_COMBO_B_CHOICE.ToString());
bool textBoxAHasContent = !String.IsNullOrEmpty(TextBoxA.Text);
bool textBoxBHasContent = !String.IsNullOrEmpty(TextBoxB.Text);
bool textBoxCHasContent = !String.IsNullOrEmpty(TextBoxC.Text);
bool primaryInformationEntered = comboBoxASelected && textBoxAHasContent && comboBSelected;
bool alternativeInformationEntered = textBoxBHasContent || textBoxCHasContent;
if (primaryInformationEntered || alternativeInformationEntered)
{
//Do Some Validation
}
Obviously, name the combo and text boxes to reflect their actual content. When someone has to work their way through the logic several months down the line they'll thank you.
a) Doesn't have to necesarily be avoided at all costs. The code works. But it is certainly messy, confusing and I would say could be difficult to maintain.
b) Yes. Give it a relevant name so that the code reader knows what is going on there.
I personally wouldn't have a big issue with code like this. (Your last set of parentheses seem unnecessary.)
Generally, I'd like to keep my if statements simpler. But all your conditions are simple ones. If you really need to test that many tests, then I'd keep it like it is.
It is not very readable yes. But you can shorten it:
!String.Equals(ComboBoxA.SelectedValue.ToString(), DEFAULT_COMBO_A_CHOICE.ToString()
could also be written as:
ComboBoxA.SelectedValue.ToString()!=DEFAULT_COMBO_A_CHOICE
I presume DEFAULT_COMBO_A_CHOICE is already of string to ToString si superflous.
also the parenthese around
(!String.IsNullOrEmpty(TextBoxB.Text)
|| !String.IsNullOrEmpty(TextBoxC.Text))
are not necessary.
IMO such conditions should be avoided (though not at all costs). They are very difficult to read an maintain.
There are several ways of doing that
Try and group the conditions according to the behavior they represent. For example
if (OrderDetailsSelected() && ShippingAddressProvided() )
{
This way you can also avoid the duplication of the conditions within your form.
Secondly, you can use the Boolean Algebra to simplify the expression and
Use Extract Method refactoring to move conditions, which are difficult to read in functions to avoid duplication and make them more readable.
For ex. The condition
String.Equals(ComboBoxB.SelectedValue.ToString(), DEFAULT_COMBO_B_CHOICE.ToString())
can be extracted into a function
private bool IsDefaultA() { return ... }
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."