C# ?: Expression - c#

I have a function with multiple if's (THIS IS NOT THE ACTUAL CODE)
if(n == 1)
m = 1;
if(n == 2)
m = 2;
if(n == 3)
m = 3;
Instead of that I wanted to do make them all into ?: expression :
(n == 1) ? m = 1;
But it says that its expecting a ':'
I am familiar with the ?: expression from C++ where you can simply write:
(n == 1) ? m = 1 : 0;
But 0 doesn't take here. This is a ridiculous question and I couldn't even find an answer in google since it ignores '?:' as a word.
ANSWER : too bad the answer was in the comments. There is no way to "do nothing" in this expression and I should use if-else or switch. thanks.

It looks like you're looking for:
m = (n == 1) ? 1 : 0;
Which you could then cascade to:
m = (n == 1) ? 1 : (n == 2) ? 2 : (n == 3) ? 3 : 0;
An important (to me, anyway), aside:
Why are you asking this? If it's because you think that this form will be more efficient than a series of if statements, or a switch, don't. The C# compiler and the .net JIT compiler are really quite clever and they'll transform your code (hopefully!) into its most optimal form. Write your code so its as understandable by yourself, or the developer who has to maintain it after you as it can be. If the performance you get isn't acceptable, then try changing it around but measure to determine what works best (bearing in mind that newer compilers/.net frameworks could well change what happens).

looking for ternary operator in c# will give you relevant results.
an example usage would be
var m = n == 1 ? 1 : 0

Maybe:
m = (n == 1) ? 1 : (n == 2) ? 2 : (n == 3) ? 3 : m;
or
m = n
Edit:
Simplified:
variable2 = (variable1 == value) ?
variable1 :
variable2;

You want this:
m = (n == 1) ? 1 : 0;
To nest them all it would look like this:
m = (n == 1) ? 1 : (n == 2) ? 2 : (n == 3) ? 3 : 0;
But as you can see, this is really a lot less easy to read and understand. It can help to add extra parenthesis, but I think you're better off using an if-else tree.

m = (n == 1) ? 1 : m
Means
M equals 1 if n == 1, else m
FYI the ? is called the Ternery operator. Find usage on MSDN
Best regards,

You could write:
m = (n==1) ? 1 : m;
But IMO that's harder to read and uglier than the original code.
(n == 1) ? m = 1 : 0;
This isn't allowed because C# doesn't allow arbitrary expressions as a statement. Method calls and assignments are allowed, most other expressions aren't.
A statement is executed for its side-effects, an expression for its value. So it's only natural that the outermost part of a statement has a side effect. ?: never has a side-effect, so it's not allowed as a statement.

Try this :
m = (n == 1) ? 1 : 0;

This is not a problem to be solved with a ternary if/else operator - it is clearly an ideal candidate for a switch statement (and using a switch is likely to be much more efficient than using a sequence of ternary operators)
If you wish to transliterate an if statement into ?:, then it's quite simple:
if ({condition}) {then-code}; else {else-code};
becomes
{condition} ? {then-code} : {else-code};
The only restriction is that the then/else code is a single statement.
The primary benefit of ?: (with modern compilers) is that it can be embedded within a statement to significantly compress the source code - sometimes this can aid readability, and sometimes it just serves to obfuscate the meaning of the code - use it with care.

Related

Understanding simple ANSI C math expression in terms of C#

I've been presented what I think is an ANSI C statement but I don't understand what it is doing or if it is even valid.
x = (y == 4) * 12 + (y == 5) * 24;
Can anyone help me understand what this statement does in terms of C# (which I actually understand).
Thanks
Historically, C did not have a boolean type.* Comparison operators returned either 0 or 1, type int. Any int value (as well as other types) could be interpreted in boolean context, where 0 means false and any other value means true.
C# treats int and bool as completely separate types. The most direct C# equivalent is
x = (y == 4 ? 1 : 0) * 12 + (y == 5 ? 1 : 0) * 24;
Which can of course be improved greatly further.
* Typically, "ANSI C" is intended to refer to the original version of C, even though later versions of C have been adopted by ANSI too. Those later versions do add a boolean type, but the comparison operators still return int values. Similarly, integers in boolean contexts are still allowed as well. They do not change anything relevant to your question.
This is definitely wrong in C#. Both expressions, y==4 and y==5 are evaluated as a boolean. That being said, how can you define the multiplication between a boolean and an integer? This expression is not correct in C#.
I would say that you could try the following:
x = (y == 4 ? 1 : 0) * 12 + (y == 5 ? 1 : 0) * 24;
In the above expression we use the ternary operator, whose logic is quite simple it the expression evaluates to true then return the result after the question mark. Otherwise it returns the value after the :. So if y is equals to 4, then (y == 4 ? 1 : 0) evaluates to 1. Otherwise, it returns 0.
The above solution is based on that hvd mentioned below in his comment, that == returns either 0 or 1 in C.

Re-writing code to remove conditional statements

Is it possible to re-write the following so that it doesn't contain any conditional statements? I'm thinking there might be some clever trick using something like bitwise operations?
int a = // some value
int b = // some other value between 0 and max int
if(b >= 3)
{
return a + 1;
}
else
{
return a;
}
EDIT: to be clear, I'm not looking for a generic way of removing conditionals. I'm looking for a trick to remove the conditionals from this very specific code. Think of it as an academic puzzle.
To give an example, one way to remove conditionals (which happens to yield perf gains in some situations) is to precompute a lookup table and index into that with b instead. In this particular case this is tricky because b could be a very large number. Is there another way?
Here you go
return a - ((2 - b) >> 31);
Explanation:
r = 2 - b, < 0 (i.e. high bit set) for b >= 3
r >> 31, = -1 for b >= 3, 0 otherwise
uint a = // some value
uint b = // some other value between 0 and max int
bool c = b & 0xFFFC
return a + Convert.ToInt32(c);
The fastest will probably be as bitwise operations tend to be very fast
uint a = // some value
uint b = // some other value between 0 and max int
return (b & 0xFFFC) ? a+1 : a;
You could make it better by doing this:
int a = // some value
int b = // some other value between 0 and max int
return (b >= 3) ? (a+1) : a;
?: operator. (but yet it contains conditional statement.)
return b >= 3 ? a + 1 : a;
or
return a + (b >= 3 ? 1 : 0);
Is it possible to re-write the following so that it doesn't contain any conditional statements?
It is not possible to make it work out of no where. you must check this condition any way. There is no magic.
If you want to make your program faster by removing this condition then you picked wrong way. this is micro optimization.

Ternary operator in actualization of a loop

I am trying to make two loops into one. This Loop should go through the array from the beginning to the end and otherwise. However my increment is not correct. Can anyone help? Thank you in advance.
for (int i = ((asc == true) ? 0 : calendar.Length - 1);
((asc == true) ? i < calendar.Length : i > 0);
(asc==true) ? i++ : i--)
Personally, I find that very hard to read, as well as invalid (it won't compile) - because you're trying to use the conditional operator as a statement expression, when it's not. Personally, I'd write something like:
for (int i = 0; i < calendar.Length; i++)
{
int index = asc ? i : calendar.Length - 1 - i;
// Now use index...
}
Making three different aspects all conditional feels like a nasty way to go.
Look at the C# reference of "for": http://msdn.microsoft.com/en-us/library/ch45axte.aspx
Specifically:
The iterator section defines what happens after each iteration of the body of the loop. The iterator section contains zero or more of the following statement expressions, separated by commas:
assignment statement
invocation of a method
prefix or postfix increment expression, such as ++i or i++
prefix or postfix decrement expression, such as --i or i--
creation of an object by using new
await expression
The expression: "(asc==true) ? i++ : i--" is none of these things.
Therefore, you'd want the assignment: i += (asc ? 1 : -1)
for (int i = ((asc) ? 0 : calendar.Length - 1);
((asc) ? i < calendar.Length : i >= 0);
i += (asc) ? 1 : -1)
Incidentally, as pointed out in comment, you'll probably want to look at index 0 in the condition, so your condition statement in the "descending" case should be i >= 0 (reflected in the code).
Jon offered a good option, but if principle:
for (int i = (asc ? 0 : calendar.Length - 1);
asc ? i < calendar.Length : i >= 0;
i += asc?1:-1)
{
//body
}
That for loop is... odd. It is also very hard to read. In the spirit of "better ways to do this", I would suggest just using Reverse:
IEnumerable<Day> collection = asc ? calendar : calendar.Reverse();
for (int i = 0; i < calendar.Length; i++)
{
collection.ElemantAt(i);// This is the current element
}
//Or better, you are getting everything anyways:
foreach (Day day in collection)
{
}

C#: Choosing operator depending on boolean value (in one line)

I'm trying to get away with a slick one liner as I feel it is probably possible.
I'll put my code below and then try to explain a little more what I'm trying to achieve.
for (int p = 0; p < 2; p++)
{
foreach (string player in players[p])
{
if (PlayerSkills[player].streak_count *>* 0) //This line
PlayerSkills[player].streak_count++;
else
PlayerSkills[player].streak_count = 0;
}
}
*(p==0 ? >:<) the comparison operator is chosen depending on p.
Of course what I've written is rubbish. But basically I want to use >0 when p==0, and <0 when p>>0. Is there a nice way to achieve this?
Well, you should use what is most readable, even if it is not as consice. That said...
// Invert the count for all but the first player and check for a positive number
if (PlayerSkills[player].streak_count * (p==0 ? 1 : -1) > 0)
I don't know about slick, but the following and/or combination is one line:
if ((p == 0 && PlayerSkills[player].streak_count > 0)
|| PlayerSkills[player].streak_count < 0)
...
This will only ever do the array index once (due to the p==0 condition occurring first) and so is equivalent to the "ternary" you wrote (albeit a bit more verbose).
p > 0 ? whenGreaterThanZero : whenZeroOrLess ;
E.g.
int p = 1; bool test = p > 0 ? true : false ;
Lets test = True

Efficiency of LINQ in simple operations

I have recently discovered LINQ and I find it very interesting to use. Currently I have the following function, and I am not sure whether it would be MORE efficient, and after all, produce the same output.
Can you please tell me your opinion about this?
The function simply removes punctuation in a very simple manner:
private static byte[] FilterText(byte[] arr)
{
List<byte> filteredBytes = new List<byte>();
int j = 0; //index for filteredArray
for (int i = 0; i < arr.Length; i++)
{
if ((arr[i] >= 65 && arr[i] <= 90) || (arr[i] >= 97 && arr[i] <= 122) || arr[i] == 10 || arr[i] == 13 || arr[i] == 32)
{
filteredBytes.Insert(j, arr[i]) ;
j++;
}
}
//return the filtered content of the buffer
return filteredBytes.ToArray();
}
The LINQ alternative:
private static byte [] FilterText2(byte[] arr)
{
var x = from a in arr
where ((a >= 65 && a <= 90) || (a >= 97 && a <= 122) || a == 10 || a == 13 || a == 32)
select a;
return x.ToArray();
}
LINQ usually is slightly less efficient than simple loops and procedural code, but the difference is typically small and the conciseness and ease of reading usually makes it worth converting simple projections and filtering to LINQ.
If the performance really matters, measure it and decide for yourself if the performance of the LINQ code is adequate.
LinQ is great to keep things simple. Performances wise, it can really become a problem if you start doing a lot of conversions to lists, arrays, and so on.
MyObject.where(...).ToList().something().ToList().somethingelse.ToList();
This is well known to be a killer, try to convert to a final list as late as possible.
Screw performance, LINQ is awsome because of this:
private static bool IsAccepted(byte b)
{
return (65 <= b && b <= 90) ||
(97 <= b && b <= 122) ||
b == 10 || b == 13 || b == 32;
}
arr.Where(IsAccepted).ToArray(); // equivalent to FilterText(arr)
I.e. you do not write the how, but just the what. Also, it's about as fast (slow) as the other method which you presented: Where(..) gets evaluated lazily in ToArray() which internally creates a List and converts that to an Array iirc.
And by the way, strings are Unicode in C#, so don't use this to do some simple string formatting (there are far nicer alternatives for that).
For the most part, I agree with #MarkByers. Linq will be a little less efficient than procedural code. Generally, the deficiency can be traced to compilation of an expression tree. Nevertheless, the readability & time improvements are worth the hit in 99% of cases. When you encounter a performance issue, benchmark, modify, and re-benchmark.
With that said, LINQ is pretty closely related to lambdas and anonymous delegates. These features are and often talked about as if they are the same thing. There are cases where these constructs can be faster than procedural code. It looks like your example can be one of those cases. I would rewrite your code as follows:
private static byte [] FilterText2(byte[] arr) {
return arr.Where( a=> (a >= 65 && a <= 90) ||
(a >= 97 && a <= 122) ||
a == 10 || a == 13 || a == 32
).ToArray();
}
Again, do some bench marks for your specific scenario, as YMMV. A lot of ink has been spilled on which is faster and under what scenarios. Here is some of that ink:
http://blog.jerrynixon.com/2010/02/revisiting-c-loop-performance.html
http://blog.thijssen.ch/2009/02/linq-vs-lambda-vs-loop-performance-test.html
In .NET, which loop runs faster, 'for' or 'foreach'?
When not to use lambda expressions
Many LINQ statements are easily parallelizable. Just add AsParallel() to the beginning of a query. You can also add AsOrdered() if you want the original order to be preserved at the expense of some performance. For example, the following LINQ statement:
arr.Where(IsAccepted).ToArray();
can be written as:
arr.AsParallel().AsOrdered().Where(IsAccepted).ToArray();
You just have to make sure its overhead doesn't outweigh its benefits:
var queryA = from num in numberList.AsParallel()
select ExpensiveFunction(num); //good for PLINQ
var queryB = from num in numberList.AsParallel()
where num % 2 > 0
select num; //not as good for PLINQ
Every good written imperative code will be more time and space effective than good written declarative code, because that declarative one must be translated to imperative one (except you own a Prolog machine ... which you probably don't, because you are asking about .Net :-) ).
But if you can solve a problem using LINQ in simpler and more readable way than using loops, it's worth it. When you see something like
var actualPrices = allPrices
.Where(price => price.ValidFrom <= today && price.ValidTo >= today)
.Select(price => price.PriceInUSD)
.ToList();
it's "one line" where it's obvious what it's doing on the first sight. Declaring a new collection, looping through old one, writing if and adding something to the new one is not. So it's a win if you don't want to save every millisecond (which you probably don't, because you are using .Net and not C with embedded ASM). And LINQ is highly optimalized - there are more codebases - one for collections, one for XML, one for SQL ..., so it is generally not much slower. No reason NOT to use it.
Some LINQ expressions can be easily parallelized using Parallel LINQ, almost "for free" (= no more code, but the parallelism overhead is still there, so count with it).

Categories