C
C#2y ago
surwren

When to use Null Forgiving (!) vs Non-Nullable casts

int? n = null;
string input;

if (int.TryParse(input,out _))
{
n = int.Parse(input);
}

int[] arr = new int[(int)n];
int? n = null;
string input;

if (int.TryParse(input,out _))
{
n = int.Parse(input);
}

int[] arr = new int[(int)n];
In this example, n needs to be cast from int? to int My question is why null forgiving (!) syntax does not seem to work (new int[n!];] and where null forgiving syntax would actually be applicable.
60 Replies
Angius
Angius2y ago
That's a very weird thing you're doing there tbh Parsing once, discarding the result of the parse, then parsing again..?
surwren
surwren2y ago
it's supposed to be
while(input==null){
if (int.TryParse(input,out _))
{
n = int.Parse(input);
}
}
while(input==null){
if (int.TryParse(input,out _))
{
n = int.Parse(input);
}
}
I omitted the while loop because the question is about null forgiving vs non-nullable casting didn't wanna detract from the main query
Angius
Angius2y ago
You're still discarding the result of parsing for some reason
surwren
surwren2y ago
I'm discarding the parse in the if statement, I'm only assigning if the if statement is fulfilled what's wrong with discarding if it's just a conditional checker?
Angius
Angius2y ago
Because then you parse it anyway
if (int.TryParse(input,out _))
{
n = int.Parse(input);
}
if (int.TryParse(input,out _))
{
n = int.Parse(input);
}
can just be
if (int.TryParse(input, out n))
{

}
if (int.TryParse(input, out n))
{

}
surwren
surwren2y ago
This is the actual code
if (int.Parse(input) < 0)
{
Console.Write("Number must be a positive integer. ");
continue;
}
else if (!int.TryParse(input, out _))
{
throw new FormatException();

}
else if (int.TryParse(input, out _))
{
n = int.Parse(input);
}
if (int.Parse(input) < 0)
{
Console.Write("Number must be a positive integer. ");
continue;
}
else if (!int.TryParse(input, out _))
{
throw new FormatException();

}
else if (int.TryParse(input, out _))
{
n = int.Parse(input);
}
I will correct it to
if (int.Parse(input) < 0)
{
Console.Write("Number must be a positive integer. ");
continue;
}
else if (!int.TryParse(input, out _))
{
throw new FormatException();

}
else if (int.TryParse(input, out n))
{ }
if (int.Parse(input) < 0)
{
Console.Write("Number must be a positive integer. ");
continue;
}
else if (!int.TryParse(input, out _))
{
throw new FormatException();

}
else if (int.TryParse(input, out n))
{ }
Angius
Angius2y ago
You can even, instead of doing
int? n = null;
if (int.TryParse(input,out _))
{
n = int.Parse(input);
}
var arr = new int[n];
int? n = null;
if (int.TryParse(input,out _))
{
n = int.Parse(input);
}
var arr = new int[n];
do
if (int.TryParse(input, out var n))
{
var arr = new int[n];
}
if (int.TryParse(input, out var n))
{
var arr = new int[n];
}
and guarantee that n will never be null Also, you're using int.TryParse(), something made explicitly for the purpose of avoiding throwing format exceptions... to throw a format exception
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
surwren
surwren2y ago
oh so that's what's triggering it smh so parse is throwing the exception
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
surwren
surwren2y ago
that's good actually it severely shortens my code
Angius
Angius2y ago
Your best bet is to parse once, with .TryParse()
surwren
surwren2y ago
and then just catch the exceptions after i will do this thank you
Angius
Angius2y ago
if (int.TryParse(input, out var num))
{
if (num < 0)
{
// ...
}
if (num % 2 == 0)
{
// ...
}

var arr = new int[num];
// etc
}
if (int.TryParse(input, out var num))
{
if (num < 0)
{
// ...
}
if (num % 2 == 0)
{
// ...
}

var arr = new int[num];
// etc
}
No Why catch exceptions int.TryParse() lets you avoid exceptions Don't make your life harder for no reason
surwren
surwren2y ago
I'm trying to intentionally throw and catch exceptions it's a learning type of thing I'm just gonna throw them more efficiently
Angius
Angius2y ago
Rethrowing an exception isn't any more efficient than letting it bubble up lol
cap5lut
cap5lut2y ago
exceptions are never efficient
surwren
surwren2y ago
yea
Angius
Angius2y ago
But sure As long as you never actually do it this way in the wild
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Angius
Angius2y ago
Kinda like learning to use a spoon by peeling an apple with it But whatever works for you
MODiX
MODiX2y ago
Sorry @surwren your message contained blocked content and has been removed!
surwren
surwren2y ago
I'm ret(@)rded ok i need to learn by getting my hands dirty this is my own way of learning exception propagation but you guys have been a great help, thank you why doesn't this board let me insult dogry
cap5lut
cap5lut2y ago
because it just detects the insult, not whom it refers to
surwren
surwren2y ago
it's not letting me do it
surwren
surwren2y ago
surwren
surwren2y ago
cap5lut
cap5lut2y ago
because its a syntax error its out <type> <variable name> u r missing the type
surwren
surwren2y ago
cap5lut
cap5lut2y ago
or is n predefined?
surwren
surwren2y ago
int? n = null;
surwren
surwren2y ago
cap5lut
cap5lut2y ago
then u cant use n as out variable because int? and int are different types
surwren
surwren2y ago
yea that's why this thread was asking specifically about nullable casts vs null forgiving so like
surwren
surwren2y ago
I have to do this then
surwren
surwren2y ago
like i was doing Hmm
Angius
Angius2y ago
Why do you need n in the outer scope
surwren
surwren2y ago
while (n == null) {}
while (n == null) {}
MODiX
MODiX2y ago
Angius#1586
if (int.TryParse(input, out var num))
{
if (num < 0)
{
// ...
}
if (num % 2 == 0)
{
// ...
}

var arr = new int[num];
// etc
}
if (int.TryParse(input, out var num))
{
if (num < 0)
{
// ...
}
if (num % 2 == 0)
{
// ...
}

var arr = new int[num];
// etc
}
React with ❌ to remove this embed.
Angius
Angius2y ago
This guarentees n will never be null
cap5lut
cap5lut2y ago
it would be more (but still not really) correct to do something like
else if (int.TryParse(input, out var tmp))
{
n = tmp;
}
else if (int.TryParse(input, out var tmp))
{
n = tmp;
}
Angius
Angius2y ago
Check for the result of int.TryParse() instead
cap5lut
cap5lut2y ago
instead of out var tmp u could also use out var tmp out int tmp as var will be inferred to int
surwren
surwren2y ago
**out var tmp** u could also use **out var tmp**
**out var tmp** u could also use **out var tmp**
huh
Angius
Angius2y ago
Prolly meant one of them to be out int tmp
cap5lut
cap5lut2y ago
uups, yes *fixing* oh its the other way around from my message 😂
Angius
Angius2y ago
I believe you can do
while (!int.TryParse(input, out var num))
{
Console.WriteLine("Not a valid integer!");
}

var arr = new int[num]; // num is a valid integer here
while (!int.TryParse(input, out var num))
{
Console.WriteLine("Not a valid integer!");
}

var arr = new int[num]; // num is a valid integer here
Since out kinda "promotes" the variable to the outer scope
cap5lut
cap5lut2y ago
isnt num out of scope after the while loop?
surwren
surwren2y ago
yeah i thought this would be it too
cap5lut
cap5lut2y ago
in c#10 it still is
Angius
Angius2y ago
Ah, huh, errors out My bad
surwren
surwren2y ago
again, I still don't know what the proper context for usage of null-forgiving vs non-nullable cast is
Angius
Angius2y ago
Null-forgiving: use it rarely if ever It's a workaround A hack around the sorry state of nullability in C# It's best to simply ensure the value isn't null And either do something if it is, or provide a default
cap5lut
cap5lut2y ago
int num;
while (!int.TryParse(input, out num))
{
Console.WriteLine("Not a valid integer!");
}

var arr = new int[num];
int num;
while (!int.TryParse(input, out num))
{
Console.WriteLine("Not a valid integer!");
}

var arr = new int[num];
should do it
Angius
Angius2y ago
Ye For example
int? num = null;

var arr = new int[num ?? 0];
int? num = null;

var arr = new int[num ?? 0];
In case num is null, replace it with 0 99% of the time, anything is better than null-forgiving
surwren
surwren2y ago
[num ?? 0]
[num ?? 0]
what syntax is this ternary?
cap5lut
cap5lut2y ago
x ?? y is short hand for x != null ? x : y so sorta yes
Angius
Angius2y ago
Null-coalescing
surwren
surwren2y ago
I'm just gonna stick to casting int?n to (int) n for now Are there other commonly used examples similar to int.TryParse that also help you to avoid exceptions?
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View