Using conditional operator ? to avoid if condition - c#

I have the following C# code
public Config(SConfig[] c)
{
GpsdIp = c[0].Ip;
GpsdPort = c[0].Port;
CompassIp = c[1]?.Ip;
CompassPort = c[1]?.Port;
}
CompassPort = c[1]?.Port; is giving a warning (red carpet)
Cannot implictly convert int? to int. Explict conversion exists are you missing a cast?
My intention here is that if the SConfig[] c contains one element it should be assigned to GpsdIp and GpsdPort. If it contains two elements then the second element should be treated as CompassIp and CompassPort. I would really like to avoid and if condition if I can.

What in your code is null conditional operator. Your correct syntax should be:
CompassIp = c.Length > 1 ? c[1].Ip : null;
CompassPort = c.Length > 1 ? c[1].Port : 0;
PS: You would get an Index out of range exception at runtime if it would be compilable.

Anything you do, other than an if statement, to accomplish the same will have more overhead than a simple if.
That said, it would seem ripe for a ternary.
public Config(SConfig[] c) {
GpsdIp = c[0].Ip;
GpsdPort = c[0].Port;
CompassIp = c.Length == 1 ? CompassIp : c[1].Ip;
CompassPort = c.Length == 1 ? CompassPort : c[1].Port;
}

You should learn the basics of C#. When trying to access at item outside array bounds, IndexOutOfRangeException is raised instead of returning default nullable value.
The solution for you is to use if operator:
if (c.Length > 1)
{
CompassIp = c[1].Ip;
CompassPort = c[1].Port;
}

Related

Null-coalescing operator inside ternary

I have this C# code:
data[j].Actual[0] = data[j].Actual.Count != 0 ? (data[j].Actual[0] ?? 0) : 0;
What I want to do is to check if the count is 0, in this case the value of the variable should be set on 0.
In case the count is different of 0, I want to check with null-coalescing operator if that value is there, otherwise return 0.
The problem I have is that I get this error message:
Index was out of range. Must be non-negative and less than the size of
the collection. Parameter name: index
My guess is that even when data[j].Actual.Count is 0 it doesn't the result to 0 but it tries to do something with the null-coalescing operator.
Any suggestions?
I think the problem is the assignment; if data[j].Actual is an empty (list/array/whatever), then you can't just assign data[j].Actual[0] to anything. If this is an array, you can't do anything (except maybe create a new array). If this is a list, you would need to .Add a value.
I would simplify the code:
var actual = data[j].Actual;
if (actual.Count == 0)
{
actual.Add(0);
// or if this is an array: data[j].Actual = new double?[] {0};
}
else if (actual[0] == null)
{
actual[0] = 0;
}
This isn't one line, but it is easy to understand.
look carefully
data[j].Actual[0] = data[j].Actual.Count != 0 ? (data[j].Actual[0] ?? 0) : 0;
You are assigning to Actual[0]. if Actual.Count is 0 you get out of range exception. you cant use ternary. use if statement.
if(data[j].Actual.Count != 0)
{
data[j].Actual[0] = data[j].Actual[0] ?? 0;
}
// else you don't need to set anything because there is nothing to set!

MVC Model: The left hand side of an assignment must be a variable, property or indexer

I have an application that I inherited, but no original code. I have decompiled the assemblies using Reflector 9, and one of the resulting Models is stuck with the error in the title. Normally this sort of error is quite simple, but this time it is baffling me. The full code is below, and the error is with the line containing
(((nullable2 = this.Variations) = nullable2.HasValue
Variations is a property defined 10 lines later in the code with
public decimal? Variations { get; set; }
The full code for the function is:
public decimal GMActual
{
get
{
decimal? nullable2;
decimal? nullable3;
decimal? pOValue = this.POValue;
if ((pOValue.HasValue ? pOValue.GetValueOrDefault() : (((nullable2 = this.Variations) = nullable2.HasValue ? new decimal?(nullable2.GetValueOrDefault()) : ((decimal?) (nullable3 = null))).HasValue ? nullable2.GetValueOrDefault() : 0M)) == 0M)
{
return 0M;
}
pOValue = this.POValue;
pOValue = this.MonthActual;
pOValue = this.POValue;
return (((pOValue.HasValue ? pOValue.GetValueOrDefault() : (((nullable2 = this.Variations) = nullable2.HasValue ? new decimal?(nullable2.GetValueOrDefault()) : ((decimal?) (nullable3 = null))).HasValue ? nullable2.GetValueOrDefault() : 0M)) - (pOValue.HasValue ? pOValue.GetValueOrDefault() : (((nullable2 = this.CostOnSage) = nullable2.HasValue ? new decimal?(nullable2.GetValueOrDefault()) : ((decimal?) (nullable3 = null))).HasValue ? nullable2.GetValueOrDefault() : 0M))) / (pOValue.HasValue ? pOValue.GetValueOrDefault() : (((nullable2 = this.Variations) = nullable2.HasValue ? new decimal?(nullable2.GetValueOrDefault()) : null).HasValue ? nullable2.GetValueOrDefault() : 0M)));
}
}
As far as I can see. I am assigning as decimal to a decimal. This is a straightforward assignment of a value, but, what am I missing?
Thanks for any suggestions
What are you trying to achieve with the code?
Are you meaning to check for equality? If so, then will need to replace the = with == in all of the occurrences in your return statements.
this doesn't really make any sense to me : (((nullable2 = this.Variations) = nullable2.HasValue, and from what i can see here, this is the condition part for the if statement. What I guess you're trying to do is something more like this :
nullable2 = this.Variations
nullable2.HasValue ? ... //and the rest of the statement
or ar you trying to check if it's not null and equal to variations? Then this should work:
(nullable2 != null && nullable2 == this.Variations) ? ...//the rest of the statement.
The decompiler seams to have messed up the code - try another one to check. How else do you want to know, that you 'fix' is the right one?
PS: Are you trying to steal that code? Its obfuscated: the original programmer seams not to want you to see that code ;).

How to handle Index out of range in a better way

My code was giving me Index out of Range exception for a certain input. Below is the problematic code:
string[] snippetElements = magic_string.Split('^');
string a = snippetElements[10] == null ? "" : "hello";
string b = snippetElements[11] == null ? "" : "world";
For that particular input, array snippetElements had only one element in it, hence while trying to index 10th and 11th element, I got the exception.
For now, I have introduced the following check:
if (snippetElements.Length >= 11)
{
string a = snippetElements[10] == null ? "" : "hello";
string b = snippetElements[11] == null ? "" : "world";
}
Can someone suggest a better way to write this check. Somehow the number 11 is not looking good in the code.
Yes this is an old post, but still helpful. You could use this which I think is cleaner:
string a = snippetElements.ElementAtOrDefault(10) ?? "hello";
string b = snippetElements.ElementAtOrDefault(11) ?? "world";
Can someone suggest a better way to write this check. Somehow the
number 11 is not looking good in the code.
Well you are accessing the element with 11 index, if you have that index in your variable then you can use that in your check, otherwise 11 is fine in your check. Your check should be if(index < snippetElements.Length)
Something like:
int index = 11;
if(index < snippetElements.Length)
{
string b = snippetElements[index] == null ? "" : "world";
}
snippetElements[11] is the 12th element.
if (snippetElements.Length >= 12)
As long your are actually using the [10] and [11] indexes it doesn't look wrong to use the 12 in the if statement.
You can generalize the problem to an extension method like this:
public static class ArrayExtensions
{
public static bool TryIndex<T>(this T[] array, int index, out T result)
{
index = Math.Abs(index);
result = default(T);
bool success = false;
if (array != null && index < array.Length)
{
result = (T)array.GetValue(index);
success = true;
}
return success;
}
}
And convert your code to:
string[] snippetElements = magic_string.Split('^');
string a = null;
string b = null;
if (snippetElements.TryIndex(10, out a) && snippetElements.TryIndex(11, out b))
{
}
Or, more like your source code and using the TryIndex(...) extension method:
string[] snippetElements = magic_string.Split('^');
string a = null;
string b = null;
snippetElements.TryIndex(10, out a);
snippetElements.TryIndex(11, out b);
a = a ?? "hello"; // Null coalesence ?? operator is great!
b = b ?? "world";
It makes the array indexed access safer since your code won't never throw ArgumentOutOfRangeException.
Note that this extension method will work for any kind of array, regardless of its type! Either if its a value type (int, byte...) or a reference type (string, your own classes...).
The logic here is wrong.
If your Split method produces less than 12 elements your indexing on the array snippetElements could go only from zero to (Length - 1) of the array.
In that case there aren't elements at index 10 or 11. And, in any case, if the snippetElement.Lenght is equal or greater than 12, then the elements in the array can't be null. Or they contain a string or they will be empty strings.
You could just write
string a = snippetElements.Length >= 12 ? "hello" : string.Empty;
string b = snippetElements.Length >= 12 ? "world" : string.Empty;
It might be late now, but for any one else who's having the same problem, that's how I solved it. I usually use this logic inside a for loop.
int index = 10;
string a = (index < snippetElements?.Length) ? snippetElements[index] : string.Empty;
snippetElements?.Length checks if snippetElements is not empty then it calls its Length property. Accessing Length property of an empty array results in an exception.
snippetElements[index] (you could replace this with "hello" as in your example) is accessed only if the index is in the bound of an array. Otherwise, it assigns String.Empty to a.

I am trying to understand what is happening in this variable assignment

I am trying to understand what is happening in this variable assignment.
num = forward.Data.Key >= key ? 1 : 0;
In particular this part >= key ? 1 : 0
To help out forward is a LinkedListCell<KeyValuePair<int, double>> forward = _data.Next;
key is an int parameter being passed into the method.
Also it is a program written in C#
That's the ternary operator. It takes a boolean expression, and returns one of two values depending on the result of that expression. You get it in a number of languages.
It's equivalent to:
if( forward.Data.Key >= key ) {
num = 1;
}
else {
num = 0;
}
It is called ternary conditional operator. (or the short If-Else statement)
value = condition ? truePart : falsePart;
The ternary operator tests a condition. It compares two values. It produces a third value that depends on the result of the comparison.
from MSDN,
int input = Convert.ToInt32(Console.ReadLine());
string classify;
// if-else construction.
if (input < 0)
classify = "negative";
else
classify = "positive";
// ?: conditional operator.
classify = (input < 0) ? "negative" : "positive";

c# Can someone explain this boolean logic

// Example bool is true
bool t = true;
// Convert bool to int
int i = t ? 1 : 0;
Console.WriteLine(i); // 1
This converts false to 0 and true to 1, can someone explain to me how the t ? 1 : 0 works?
Look at the Ternary Operator.
int i = t ? 1 : 0;
Equates to:
if(t)
{
i = 1;
}
else
{
i = 0;
}
This syntax can be found in a variety of languages, even javascript.
Think of it like an English sentence if you swap the colon for "otherwise":
bool isItRaining = false;
int layersOfClothing = isItRaining? 2 otherwise 1;
It's the C# Conditional Operator.
i = does t == true? if yes, then assign 1, otherwise assign 0.
Can also be written as:
if (t == true)
t = 1;
else
t = 0;
or
if (t)
t = 1;
else
t = 0;
Since t is true, it prints 1.
if t equels true then i=1 else i=0
ternary operator
bool t= true;
int i;
if(t)
{
i=1;
}
else
{
i=0;
}
For more look ?: Operator
(? *) this is conditional operator.
The conditional operator (?:) returns one of two values depending on the value of a Boolean expression. The conditional operator is of the form
condition ? first_expression : second_expression;
here in you case (true?1:0 ) since the condition is true ,which is certainly setting value of i to 1.
I believe that internally the compiler will inline the statement to the equivalent of:
Console.WriteLine(Convert.ToInt32(t));
This Convert.x method checks to see if the passed parameter is true return 0 if it isn't.

Categories

Resources