IsTrue:TrueCondition:FalseCondition Evaluates Both Conditions - c#

I discovered a very puzzling behavior for the following code:
public double ReturnBehavior(List<double> ptList)
{
return ptList.Count==0? 0:ptList[0];
}
I thought it should be equivalent to
public double ReturnBehavior(List<double> ptList)
{
if(ptList.Count==0)
return 0;
return ptList[0];
}
But it is not, because the first method will evaluate both true and false condition together. So this means that first method will try an IndexOutOfRange exception if ptList.Count==0.
Am I missing something here? Or is it a bug in vs 2008?

I've checked both in VS2010 and VS2008, behavior is expected - no exceptions. If you have errors - they are not in the given code fragment

They ought to behave the same. The ternary operator uses short-circuit semantics. If the test passes, only the first expression is evaluated, otherwise, only the second expression is evaluated. Are you actually seeing an exception?

I think that in some cases, if you have a multicore processor, the compiler will tell the processor to evaluate ahead if possible. At least i know that's the case when for example i have an if(condition1 && condition2), on some computers it will evaluate both conditions in parallel, and this means it evaluates the second condition even if the first fails.

Related

Null-coalescing out parameter gives unexpected warning

Using this construct:
var dict = new Dictionary<int, string>();
var result = (dict?.TryGetValue(1, out var value) ?? false) ? value : "Default";
I get an error saying CS0165 use of unassigned local variable 'value' which is not what I expect. How could value possibly be undefined? If the dictionary is null the inner statement will return false which will make the outer statement evaluate to false, returning Default.
What am I missing here? Is it just the compiler being unable to evaluate the statement fully? Or Have I messed it up somehow?
Your analysis is correct. It is not the analysis the compiler makes, because the compiler makes the analysis that is required by the C# specification. That analysis is as follows:
If the condition of a condition?consequence:alternative expression is a compile-time constant true then the alternative branch is not reachable; if false, then the consequence branch is not reachable; otherwise, both branches are reachable.
The condition in this case is not a constant, therefore the consequence and alternative are both reachable.
local variable value is only definitely assigned if dict is not null, and therefore value is not definitely assigned when the consequence is reached.
But the consequence requires that value be definitely assigned
So that's an error.
The compiler is not as smart as you, but it is an accurate implementation of the C# specification. (Note that I have not sketched out here the additional special rules for this situation, which include predicates like "definitely assigned after a true expression" and so on. See the C# spec for details.)
Incidentally, the C# 2.0 compiler was too smart. For example, if you had a condition like 0 * x == 0 for some int local x it would deduce "that condition is always true no matter what the value of x is" and mark the alternative branch as unreachable. That analysis was correct in the sense that it matched the real world, but it was incorrect in the sense that the C# specification clearly says that the deduction is only to be made for compile-time constants, and equally clearly says that expressions involving variables are not constant.
Remember, the purpose of this thing is to find bugs, and what is more likely? Someone wrote 0 * x == 0 ? foo : bar intending that it have the meaning "always foo", or that they've written a bug by accident? I fixed the bug in the compiler and since then it has strictly matched the specification.
In your case there is no bug, but the code is too complicated for the compiler to analyze, so it is probably also too complicated to expect humans to analyze. See if you can simplify it. What I might do is:
public static V GetValueOrDefault<K, V>(
this Dictionary<K, V> d,
K key,
V defaultValue)
{
if (d != null && d.TryGetValue(key, out var value))
return value;
return defaultValue;
}
…
var result = dict.GetValueOrDefault(1, "Default");
The goal should be to make the call site readable; I think my call site is considerably more readable than yours.
Is it just the compiler being unable to evaluate the statement fully?
Yes, more or less.
The compiler does not track unassigned, it tracks the opposite 'defintely assigned'. It has to stop somewhere, in this case it would need to incorporate knowledge about the library method TryGetValue(). It doesn't.

Can XPathNavigator.Evaluate(string) return null?

Can this overload of XPathNavigator.Evaluate return null ?
// Can "result" be null ?
object result = xmlDoc.CreateNavigator().Evaluate(xpathString);
If the answer is No, then why Resharper says that result maybe null ?
string str = result.ToString(); // Resharper: Possible NullReferenceException
I found nothing in the documentation about an input that might cause it to return null. I also tried inspecting the Reference Source for this function, but it was unfruitful.
I know that R# uses code annotations, but I still don't trust this warning as I tried different inputs with none of them returns null.
Looking at the code, it does look like it would be highly unlikely to get a null from XPathNavigator.Evaluate. There are a couple of possible code paths that might get you a null, but I suspect they're pathological edge cases (if evaluating a function that should be a number function, but isn't, or if the operand to a query is already null). I doubt these would happen under normal circumstances.
I don't know why ReSharper has the [CanBeNull] annotation on the return value. If I had to guess, I'd say it's because the method is virtual, and therefore there's no way to guarantee that the implementation will always return a value. Or because it calls an abstract method on another class that doesn't have any null-ness guarantees, and there's no check on the return of that value, so again, there's no guarantee that it won't be null.
The annotations are based on static control flow analysis, and that can only get you so far. ReSharper will provide the strongest hints that it can. If it knows it's not null, it will annotate it so, if it doesn't know, it will flag it [CanBeNull], and err on the side of caution.

Is It Possible to have the Compiler Automatically Optimize my "OR" Statements?

Is there a way to make the C# compiler optimize my OR clauses in an if statement?
For example:
if(Function_that_returns_boolean() || boolean_value)
{
// Do something here...
}
Could have hugely different execution times than
if(boolean_value || Function_that_returns_boolean())
{
// Do something here...
}
depending on how much work Function_that_returns_boolean() actually does internally.
It's unlikely (and perhaps impossible) that the compiler could know exactly how efficient Function_that_returns_boolean() is, and all of my (brief) testing indicates OR statements are always processed left to right, even under using the most aggressive compiler optimizations.
Is this already handled by the compiler (i.e. am I mistaken)? If not, are there any hints I can give to it?
Maybe something like an Attribute that lets the compiler know that it's free to rearrange my code (and if not present, to leave it be)?
[OrStatementUsage(Speed.Fast)] // Always push statement left when possible
public bool Fast_function_that_returns_boolean()
{
return a + b == c; // fast
}
[OrStatementUsage(Speed.Slow)] // Always push statement right when possible
public bool Slow_function_that_returns_boolean()
{
Thread.Sleep(1000);
return a + b == c; // slow
}
(Note: all methods in the statement would have to be tagged and side-effect free to be candidates for rearrangement)
http://msdn.microsoft.com/en-us/library/6373h346.aspx
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.
The first operand will always be evaluated. This is a very important guarantee:
if (obj == null || obj.foo == "bar")
If the compiler could reorder the conditions here, it would change the functionality of the program.
The compiler can't know whether a given reordering would affect the result -- both because it can't in general know what the result will be and because it doesn't know what parts of the result are important. Maybe you want a long delay, or the first calculation does something important for the correctness of the program.
No, the first argument is evaluated, and if it is true, the second argument is not evaluated at all. It is called "short-circuit" evaluation.
See http://msdn.microsoft.com/en-us/library/6373h346.aspx.
There is no way to instruct the compiler to evaluate the second argument of || first.
No, boolean logic operators are always short-circuit evaluated. In case of an or, the second part might not even be evaluated if it already evaluated to true. For instance:
if(ReturnTrue() || SlowOperation()) { /* ... */ }
Assuming that ReturnTrue() returns true, SlowOperation() is never called. The compiler cannot make optimization based on some arbitrary assumptions

Assert Index was out of range. Must be non-negative and less than the size of the collection

I have this assertion and it throws me an error even when count is 0.
Assert.IsTrue(list.Count==0,String.Format("It could not be opened for {0} topic, starting with {1}"list.Count,list[0]));
I find it strange because since the assertion is true, then why is the message still being evaluated? or am i missing sth here?
I find it strange because since the assertion is true, then why is the message still being evaluated?
Because IsTrue is a method of the Assert class. The compiler evaluates both arguments and then passes them to the function. Evaluating the second argument fails, before the function is even called.
The IsTrue method and doesn't have short circuiting semantics like && or ||. All of the arguments will be evaluated in order unless one of them throws an exception
The message is evaluated before the assertion is called. It is a parameter that is sent to the IsTrue-method, so string.Format is called before.
There is no magic implementation that first evaluates the expression to be asserted and then builds the message only if it is needed.
String.Format is executed before calling Assert.IsTrue() - hence it gives an error if the list is empty regardless of what Assert.IsTrue() does.
Note that this is the case for any function call in C#: all the parameters are evaluated first, and then the results of the evaluation are passed to the function.

C# bool expression evaluation order [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
== Operator and operands
Possible Duplicates:
Is there any difference between if(a==5) or if(5==a) in C#?
== Operator and operands
Ok, this may be stupid question, but searching in google (cant seem to ACTUALLY search for an exact phrase even with quotes)
What if any difference is there between
if(false == <somecondition>){
and
if(<somecondition> == false){
in C#? I am familiar with c#'s expression evalution, and understand how the order would make sense if you were doing something like:
if(AccountIsInvalid || AccountIsUnregistered)
I dont need a huge lesson, but would like to understand why some people prefer to do things with false==.... route.
Personally, I never compare anything to false or true.
I would go with:
if (!somecondition)
or:
if (somecondition)
In C there would have been, perhaps, some reason to do this as you could easily make a mistake and use the assignment operator instead of the comparison operator, but in C# it shouldn't make any difference -- you'll get a compile warning if you use the assignment operator. If the assignment were a different type (say int), it would result in an error, since the result wouldn't be a legal expression for the if statement.
I would prefer it to be
if (!<somecondition>)
{
...
}
rather than a comparison to false (or true, for that matter).
Before performing any optimizations or short-circuits, the compiler needs to resolve <somecondition> to true or false value, thus there is no reason why the compiler would evaluate the expressions <somecondition> == false and false == <somecondition> any differently.
This must surely be an issue of style, and style only.
This doesn't matter in C# like it does in c/c++ because conditions must evaluate to a boolean.

Categories

Resources