RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

nullchecking - is this safe?

David

Moderate
daat99;628662 said:
Code:
if ( m != null && m.Mana >= 50)
This will NEVER crash in c# (it may on vb depends on your compilation settings).
I have to agree with daat99 on this one... :cool:
 
arul;629159 said:
Then you probably used a wrong operator. Replacing '&&' with only '&' is a common mistake.


did you read the line that threw the exception - it is an && there and not just an & - it would not eeven compile if i used just an & there

it may not check the 2nd half on a null check, but it does when it is not a null check
 

arul

Sorceror
Lord_Greywolf;629215 said:
did you read the line that threw the exception - it is an && there and not just an & - it would not eeven compile if i used just an & there

it may not check the 2nd half on a null check, but it does when it is not a null check
Yes, I did. Though I don't believe it's the same line that threw the exception you mentioned.

As for compiling with '&', it would compile just fine, there's no reason why it shouldn't. And even more, it would have thrown the exception you mentioned! *blink*

Prove your point or stop misleading people with your distorted thoughts about C#.
 

daat99

Moderator
Staff member
Lord_Greywolf;629215 said:
did you read the line that threw the exception - it is an && there and not just an & - it would not eeven compile if i used just an & there

it may not check the 2nd half on a null check, but it does when it is not a null check

Seperating the if statement into 2 lines will still throw the invalid cast exception.

Again if you disagree than show some code and relevant crash log, you won't get it...
What you're saying is impossible because of a simple fact.
PackHorse can and will not be null so it'll pass the first check regardless if it's on the same line or not, this will crash on the second line.

Up to this point I showed real code that you didn't even bothered to test yourself while you only quoted what you "remember".
Show some real code that support your claim and stop quoting your memory because you're confusing 2 different things.
Once you'll try to reproduce your crash you'll see that you did 2 different things and you'll see your confusion.

What you did was changing:
Code:
if ( o [B]!= null[/B] && o.class > 4 )
with:
Code:
if ( o [B]is B[/B] )
   if ( ((B)o).class > 4 )
Notice that the first part of the if statement is different, separating the lines themself have no effect whatsoever on the compiling code:
This is the same:
Code:
if ( o [B]is B[/B] [B][COLOR="Red"]&&[/COLOR][/B] ((B)o).class > 4 )



arul;629230 said:
As for compiling with '&', it would compile just fine, there's no reason why it shouldn't. And even more, it would have thrown the exception you mentioned! *blink*

Actually single & will do bitwise check between 2 numbers.
While the second part of the if statement will return a number the first part will return a boolean.
I think (99%) it won't compile that particular mistake but I can't check this atm so I'm not 100% sure.
 

arul

Sorceror
daat99;629323 said:
Actually single & will do bitwise check between 2 numbers.
While the second part of the if statement will return a number the first part will return a boolean.
I think (99%) it won't compile that particular mistake but I can't check this atm so I'm not 100% sure.

It compiles just fine with '&', and works the same way as the '&&' does, except the expected short-circuit evaluation, hence the invalid cast exception.
 
daat99;629323 said:
Seperating the if statement into 2 lines will still throw the invalid cast exception.

Again if you disagree than show some code and relevant crash log, you won't get it...
What you're saying is impossible because of a simple fact.
PackHorse can and will not be null so it'll pass the first check regardless if it's on the same line or not, this will crash on the second line.

Up to this point I showed real code that you didn't even bothered to test yourself while you only quoted what you "remember".
Show some real code that support your claim and stop quoting your memory because you're confusing 2 different things.
Once you'll try to reproduce your crash you'll see that you did 2 different things and you'll see your confusion.

What you did was changing:
Code:
if ( o [B]!= null[/B] && o.class > 4 )
with:
Code:
if ( o [B]is B[/B] )
   if ( ((B)o).class > 4 )
Notice that the first part of the if statement is different, separating the lines themself have no effect whatsoever on the compiling code:
This is the same:
Code:
if ( o [B]is B[/B] [B][COLOR="Red"]&&[/COLOR][/B] ((B)o).class > 4 )

Actually single & will do bitwise check between 2 numbers.
While the second part of the if statement will return a number the first part will return a boolean.
I think (99%) it won't compile that particular mistake but I can't check this atm so I'm not 100% sure.

did you read what i posted? i said it did not throw a null in that case - it threw a different exception, but still crashed the shard - i posted the crash line that stated that

also the single "&" works with numbers, because they can be converted to bool
other types of things will not compile because they can not be converted to bool - that is the error it gives, so with intigers, a single "&" works, and does with other things, but not all things, in the case of my items a single "&" would not compile

and converting mine into 2 seperate lines did work as long as the 2nd was a sub of the 1st

if ( root is PlayerMobile)
{
if ((PlayerMobile)root).ClassLevel <= 4)
{
code here
}
}
then it does not throw exception
 

mordero

Knight
Code:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            ClassA var = new ClassA();
            var.Name = "Test";
            ClassBase o = var;
            try
            {
                //will not throw exception
                if ((o is ClassB) && (((ClassB)o).Name == "Test"))
                    Console.WriteLine("True 1");
                else
                    Console.WriteLine("False 1");
            }
            catch (Exception er)
            {
                Console.WriteLine("First");
                Console.WriteLine(er.Message);
            }
            Console.WriteLine();
            try
            {
                //will throw exception, notice only 1 &
                if ((o is ClassB) & (((ClassB)o).Name == "Test"))
                    Console.WriteLine("True 1");
                else
                    Console.WriteLine("False 1");
            }
            catch (Exception er)
            {
                Console.WriteLine("Second");
                Console.WriteLine(er.Message);
            }
            Console.WriteLine();
            try
            {
                //will not throw exception
                if ((o is ClassB))
                {
                    if (((ClassB)o).Name == "Test")
                        Console.WriteLine("True 2");
                }
                else
                    Console.WriteLine("False 2");
            }
            catch (Exception er)
            {
                Console.WriteLine("Third");
                Console.WriteLine(er.Message);
            }
            Console.WriteLine();
            try
            {
                //throws exception (duh)
                if ((o is ClassA) && (((ClassB)o).Name == "Test"))
                    Console.WriteLine("True 3");
                else
                    Console.WriteLine("False 3");
            }
            catch (Exception er)
            {
                Console.WriteLine("Fourth");
                Console.WriteLine(er.Message);
            }
            Console.ReadLine();
        }
    }

    //classes that were used to test, both ClassA and ClassB inherit ClassBase (player PlayerMobile and BaseCreature do Mobile)
    class ClassA : ClassBase
    {
        private string m_name;
        public string Name
        {
            get { return m_name; }
            set { m_name = value; }
        }
    }
    class ClassB : ClassBase
    {
        private string m_name;
        public string Name
        {
            get { return m_name; }
            set { m_name = value; }
        }
    }
    class ClassBase
    {
        private int m_id;
        public int ID
        {
            get { return m_id; }
            set { m_id = value; }
        }
    }
}

As you can see when you run this, the First and Third are fine. They are identical in terms of boolean logic. However, if you look at the second one, using only 1 & will throw a cast error because its still checking the second one (because & is bitwise, so it has to check the second one). So using what you are using would be the third one, but it is identical to the first, so it couldnt be your problem.
 
try making classb a sub of classa - like so:

class ClassB : ClassA

then

Code:
        private string m_name2;
        public string Name2
        {
            get { return m_name2; }
            set { m_name2 = value; }
        }

then set up o to be a classA item

and do the check
if (item is classB && (classB)item.name2 == "abcd")
if (item is classB & (classB)item.name2 == "abcd")

and see what errors you get on the 2nd line - and the crash that will occor with the 1st if the item is a classA only on not a classB

I did test the line i submitted --- it was that line that caused the crash - i had it write lines of "stage 1 complete", etc all through the script until i found the line causing the crash

As I said - It must be a Subset of the 1st one - as in playermobile is a subset of mobile

you guys are doing apples and oranges, i am doing apples and michigan apples - big difference for comparing

ps - i never used the single "&" in that line of code i submitted - was always 2 as in "&&" so the single "&" is a mute point in my testing of it
 
no it is not - you classB and ClassA are both Baseclass not a subset of each other - that is where a difference comes in

or do what i did - in stealing.cs - add in the line i put in - but use something else that playermobiles have that mobiles do not have - and try to steal from a pack horse - you will get the crash - i put the crash report in there - and it was that line that caused it - take it out - no crash what more can i say - it caused the crash
 

noobie

Wanderer
greywolf, that code you have written doesnt crash unless you use bitwise operator "&" instead of logical operator "&&".

and you can use bitwise operators with boolean values.

btw, you cant cast class A to class B where neither one is some related to other. the compiler wont allow that..
 

mordero

Knight
noobie;629588 said:
greywolf, that code you have written doesnt crash unless you use bitwise operator "&" instead of logical operator "&&".

and you can use bitwise operators with boolean values.
But a single & will check both operands, which would cause a cast exception. So thats why you would use &&

btw, you cant cast class A to class B where neither one is some related to other. the compiler wont allow that..
Of course
 

daat99

Moderator
Staff member
arul;629501 said:
It compiles just fine with '&', and works the same way as the '&&' does, except the expected short-circuit evaluation, hence the invalid cast exception.

I didn't knew about that, thanks :)

Lord_Greywolf said:
and converting mine into 2 seperate lines did work as long as the 2nd was a sub of the 1st
If you were using && than separating the lines would still throw the exact same crash.

mordero;629558 said:
As you can see when you run this, the First and Third are fine. They are identical in terms of boolean logic. However, if you look at the second one, using only 1 & will throw a cast error because its still checking the second one (because & is bitwise, so it has to check the second one). So using what you are using would be the third one, but it is identical to the first, so it couldnt be your problem.
Thanks for the example code.


Greywolf, up to this point we all showed a compilable code and explained what it does with the exception of you.
You only showed theoretical code and "claimed" that it does something while you haven't even tested it.
Please put up some code some code that you think will support your claim and try to compile it, if it does support your claim than I do want to see how it's written and what crash you get from it.

P.S.
I also would like to see how the code doesn't crash if you separate the lines but do crash if you combine them with &&.
 
i all ready did put up that code, the crash report from it and how i seperated the lines so it would not cause the crash - it is all in there all ready

but here it is again:

the line that caused the crash:

Code:
if ( root is PlayerMobile && ((PlayerMobile)root).ClassLevel <= 4)

the crash report from it - what i have left - it has been deleted:

Code:
System.InvalidCastException: Unable to cast object of type 'Server.Mobiles.PackLlama' to type 'Server.Mobiles.PlayerMobile'.

and how i made it on seperate lines nested so it does not throw it:

Code:
	if ( root is PlayerMobile)
	{
		if ((PlayerMobile)root).ClassLevel <= 4)
		{
		code here for what it does
		}
	}
 

Malaperth

Wanderer
I have also experienced crashes from that sort of coding and have not understood, as I thought that with any && statement, the first evaluation on the left had to be true (which in the case of the PackLlama, it would not be), for the second evaluation to even be attempted.
 

daat99

Moderator
Staff member
Lord_Greywolf;629651 said:
i all ready did put up that code, the crash report from it and how i seperated the lines so it would not cause the crash - it is all in there all ready

but here it is again:

the line that caused the crash:

Code:
if ( root is PlayerMobile && ((PlayerMobile)root).ClassLevel <= 4)

the crash report from it - what i have left - it has been deleted:

Code:
System.InvalidCastException: Unable to cast object of type 'Server.Mobiles.PackLlama' to type 'Server.Mobiles.PlayerMobile'.

and how i made it on seperate lines nested so it does not throw it:

Code:
	if ( root is PlayerMobile)
	{
		if ((PlayerMobile)root).ClassLevel <= 4)
		{
		code here for what it does
		}
	}
Again, this code is from your memory and not a currently compiled code like the code we posted above.

Since it becomes clear that you are unwilling to actually test the code you posted and since what you posted is going against the c# language and was proven incorrect by mordero's code above, I'm going to stop trying to make you understand your mistake for now.

Once you'll put in some time testing into your claims I'll try again.
 

noobie

Wanderer
Code:
	if ( root is PlayerMobile)
	{
		if ((PlayerMobile)root).ClassLevel <= 4)
		{
		 //code
		}
	}


Code:
if ( root is PlayerMobile && ((PlayerMobile)root).ClassLevel <= 4){
//code
}

these codes are completely identical. the second term is evaluated only if the first one is true. and while you are using || operator, the second one is evaluated only if the first one is false.

there is no way, one of them is working properly and the other is not.
 
Top