Click to See Complete Forum and Search --> : overloading short-circuit operators and indexers


ironman
March 20th, 2005, 04:58 PM
I`m having difficulty understanding the working of short-circuit operators.How is only the first object evaluated etc.And having a tough time with indexers as well.I`d appreciate if anyone explains these two topics in simple terms to me.Thanks

cilu
March 21st, 2005, 02:51 AM
An indexer provides a natural way to index elements in a class or struct that encapsulates a collection, using the open and closed bracket ([]) syntax of the array type. For example:

public class ScoreList {
int[] scores = new int [5];
// indexer
public int this[int index]
{
get { return scores[index]; }
set
{
if(value >= 0 && value <= 10)
scores[index] = value;
}
}
// property (read-only)
public int Average
{
get
{
int sum = 0;
foreach(int score in scores)
sum += score;
return sum / scores.Length;
}
}
}
class IndexerTest {
static void Main( ) {
ScoreList sl = new ScoreList( );
sl[0] = 9;
sl[1] = 8;
sl[2] = 7;
sl[3] = sl[4] = sl[1];
System.Console.WriteLine(sl.Average);
}
}


Indexers are compiled to get_Item (...)/set_Item (...) methods, which is their representation in MSIL:


public Story get_Item (int index) {...}
public void set_Item (int index, Story value) {...}


Consequently, you cannot define a property named Item in a type that has an indexer.

CoffeeMug
March 21st, 2005, 03:09 AM
As for the short-circuit operators (|| and &&), the first expression is always evaluated first. If this one is true, then the second (and possibly third etc) is evaluated. So if you have to compare 2 things and the first one returns false, it's of no use to evaluate the second one too, since the first one already failed anyways. You can imagine that it's of no use to evaluate things if the CLR already knows that one of them failed.

Simple example of &&:
Let's say someone asks you to run an errand. This person tells you "I want all of the things you see on the list, but if you can't find one of them, don't bother getting any of them at all."
Now, you go to the store, and what do you do? You check the first thing on your list of errands. If you find this, you can go on searching. If you don't find this, why would you go through the trouble getting the other stuff if you already know the first thing you needed wasn't in the store? Better go home, saves you a lot of time! :D

Simple example of ||:
That same person wants you to get some more stuff. He tells you "If you can't find A, then get me B."
Now you are in the store again, and what do you do? You check the first thing on your list again. This time, if you can't find it, you were asked to get something else (B). This means you will have to go and get that, since you didn't find A.
If you did find A, why would you go through the trouble of getting B? You already have A!

Hope it helps.
Vincent

EDIT: forgot to add the OR operator.

ironman
March 21st, 2005, 01:37 PM
Thanks for the replies ppl.

Actually I know how short-circuit operators work. But I don`t understand how they work when you overload them.Why the 4 necessary condition are required and how they work together?

cilu
March 21st, 2005, 04:35 PM
What are you talking about. You cannot override the logical boolean operators || (OR), && (AND) or ternary conditional ?: ; Nor the bitwise operators & (AND), | (OR), ^ (XOR). Nor

primary
Grouping: (x)
Member access: x.y
Struct pointer member access: ->
Method call: f(x)
Indexing: a[x]
Constructor call: new
Array stack allocation: stackalloc
Type retrieval: typeof
Struct size retrieval: sizeof
Arithmetic check on: checked
Arithmetic check off: unchecked

unary
Value at address: *
Address of value: &

relational
Type equality/compatibility: is
Conditional type conversion: as

darwen
March 21st, 2005, 05:12 PM
Besides that, what's a short-circuit operator ?

Darwen.

darwen
March 21st, 2005, 05:16 PM
Ah, it's a course-ism. Another quick search brought up a terminology that
no-one uses past the lecture theatre. *laugh*

It means which parameter in a boolean statement is considered first.

Like in C++ if I write :


int nValue = 100;
if (FALSE && nValue == 100)
{
// never called because FALSE rejects all other values
}


The boolean evaluation in C# is the same as in C++, so there you go.

Darwen.

Issa
March 21st, 2005, 05:22 PM
It means which parameter in a boolean statement is considered first.

The boolean evaluation in C# is the same as in C++, so there you go.


is order of evaluation defined for like logical operators? as in


firstVar && secondVar && thirdVar


is it defined behavior that firstVar and secondVar are compared first?

i can't remember if i'm recalling c++ or java, but i think this is unspecified.

darwen
March 21st, 2005, 05:35 PM
In C++ it's undefined but (and here's a quantum leap) I believe in C# it is defined as first boolean comparison evaluated first.

Darwen.

darwen
March 21st, 2005, 06:04 PM
Besides the fact - who cares ? Try it, find out - if it works use it.

All this "official" talk is doing my head in. Go and write an application guys...

Darwen.

cilu
March 22nd, 2005, 03:34 AM
Besides that, what's a short-circuit operator ?
I didn't know that either. Never heard this term for logical boolean operators before... :ehh: ;)

PseudoBill
March 22nd, 2005, 10:05 AM
The term "short-circuit" logical operator is actually quite common among ex-VB progammers since the original VB logical operators (And & Or) would not short-circuit, but evaluate everything (identical to | and & in C#). Only in .NET does VB have operators that are the equivalent to && and ||, and those are AndAlso and OrElse (very ugly, but we're talking about VB here...)

PseudoBill
March 22nd, 2005, 10:16 AM
I think | and & are overloadable (|| and && aren't, but there behavior is defaulted if | and & are overloaded - i.e., the second expression isn't evaluated.

cilu
March 22nd, 2005, 10:34 AM
I think | and & are overloadable (|| and && aren't, but there behavior is defaulted if | and & are overloaded - i.e., the second expression isn't evaluated.
Yes, seems that binary operators |, &, ^ can be overloaded after all.

ironman
March 22nd, 2005, 03:29 PM
yup cilu, we can overload the binary operators | and &. And we can even overload them in such a way that enables the && and || operators.In this case the & and | returns an object(i think) such as: return new ThreeD(0,0,0)( example from my book). But I don`t understand why? and a few other things which I don`t understand .I was basically looking if someone could explain me these important things which are different from usual & and | overload.

cilu
March 22nd, 2005, 04:41 PM
yup cilu, we can overload the binary operators | and &. And we can even overload them in such a way that enables the && and || operators.In this case the & and | returns an object(i think) such as: return new ThreeD(0,0,0)( example from my book). But I don`t understand why? and a few other things which I don`t understand .I was basically looking if someone could explain me these important things which are different from usual & and | overload.
Wel, posting the example would help explaining it.

ironman
March 24th, 2005, 03:54 PM
Here`s the example straight from my book!


using System;

// A three-dimensional coordinate class

class ThreeD{
int x,y,z;//3-D coordinates

public ThreeD(){x=y=z=0;}

public ThreeD(int i,int j,int k){x=i;y=j;z=k;}

//overload | for short-circuit evaluation.
public static ThreeD operator |(ThreeD op1,ThreeD op2)
{
if((op1.x !=0) || (op.y !=0)||(op1.z!=0))|
((op2.x!=0)||(op2.y!=0)||(op2.z!=0)))
return new ThreeD*(0,0,0);
}


//overload & for short-cicuit evaluation.
public static ThreeD operator &(ThreeD op1,ThreeD op2)
{
if(((op1.x!=0)&&(op1.y!=0)&&(op1.z!=0))&
((op2.x!=0)&&(op2.y!=0)&&(op2.z!=0)))
return new ThreeD(1,1,1);
else
return new ThreeD(0,0,0);
}

//Overload !.

public static bool operator!(ThreeD op)
{
if(op)return false;
else return true;
}
//Overload true.
public static bool operator true(ThreeD op)
{
if((op.x!=0)||(op.y!=0)||op.z!=0))
return true;//at least one coordinate is non-zero
}
//Overload false
public static bool operator false(ThreeD op)
{
if((op.x==0)&&(op.y==0)&&(op.z==0))
return true;//all cordianates are zero
else return false;
}
//show x,y,z coordinates.
public void show()
{
Console.WriteLine(X+","+Y+","+Z);
}}

class TrueFlaseDemo{
public static void Main()
{
ThreeD a=new ThreeD(5,6,7);
ThreeD b=new ThreeD(10,10,10);
ThreeD c=new ThreeD(0,0,0);

Console.WriteLine("Here is a: ");
a.show();

Console.WriteLine("Here is b: ");
b.show();

Console.WriteLine("Here is c: ");
c.show();


if(a)Console.WriteLine("a is true.");
if(b)Console.WriteLine("b is true.");
if(c)Console.WriteLine("c is true.");

if(!a)Console.WriteLine("a is false.");

if(!b)Console.WriteLine("b is false.");

if(!c)Console.WriteLine("c is false.");

Console.WriteLine();

Console.WriteLine("Use & and |");

if(a&b)Console.WriteLine("a &b is true.");
else Console.WriteLine("a &b is false.");


if(a&c)Console.WriteLine("a &c is true.");
else Console.WriteLine("a &c is false.");

if(a|b)Console.WriteLine("a |b is true.");
else Console.WriteLine("a |b is false.");

if(a|c)Console.WriteLine("a |c is true.");
else Console.WriteLine("a |c is false.");

Console.WrieLine();

//now use short-circuit ops.

Console.WriteLine("use short circuit && and ||");

if(a&&b)Console.WriteLine("a && b is true.");
else Console.WriteLine("a && b is false.");


if(a&&c)Console.WriteLine("a && c is true.");
else Console.WriteLine("a && c is false.");


if(a||b)Console.WriteLine("a ||b is true.");
else Console.WriteLine("a || b is false.");

if(a||c)Console.WriteLine("a ||c is true.");
else Console.WriteLine("a || c is false.");



}
}



I dont understand how only the first expression is evaluated in these condions which use short-circuit && and ||. Thanks

ironman
March 25th, 2005, 05:58 AM
Her`s an example from my book of indexers.I have put questions along with the steps I dont understand.




using System;

class failsoftarray
{
int[]a;//reference to an underlying array
public int length;//length is public
public bool errflag;//indicates outcome of last operation

//construct array given its size.
public failsoftarray(int size)
{
a=new int[size];
length=size;
}

//this is the indexer for failsoftarray
public int this[int index]
{
get
{
if(ok(index))
{
errflag=false;
return a[index];
}
else
{
errflag=true;
return 0;
}
}
set
{
if(ok(index))
{
a[index]=value;
errflag=false;
}
else errflag=true;
}
}
//return true ifd index is within bounds
private bool ok(int index)
{
if(index>=0&index<length)return true;
return false;
}
}

//demo failsoftarray
class fsdemo
{
public static void Main()
{
failsoftarray fs=new failsoftarray(5);
int x;
//show quiet failure
Console.WriteLine("FAIL QUIETLY");
for(int i=0;i<(fs.length*2);i++)
fs[i]=i*10; at this point the loop will run extra times but will not assign values to the underlying array,but will there be any use to set the error flag true each extra time a value is sent to the set accessor?
for(int i=0;i<(fs.length*2);i++)
{
x=fs[i];
if(x!=-1)Console.Write(x+" ");why are we assigning the values to x can`t we jst print fs[i]?
}
Console.WriteLine();

//now generate failures
Console.WriteLine("\nfail with error reports");

for(int i=0;i<(fs.length*2);i++)
{
fs[i]=i*10;why are we assigning values to fs[i] again?doesn`t it already contain values?
if(fs.errflag)
Console.WriteLine("fs["+i+"]out of bound");
}

for(int i=0;i<(fs.length*2);i++)
{
x=fs[i];here again,why are we assigning vaues to x again??
if(!fs.errflag)Console.Write(x+" ");
else
Console.WriteLine("fs["+i+"] out of bound");
}

}
}

cilu
March 25th, 2005, 07:54 AM
First, please use CODE tags.

This

int[]a;//reference to an underlying array
public int length;//length is public

//construct array given its size.
public failsoftarray(int size)
{
a=new int[size];
length=size;
}

I would put it like this:

int[]a; //reference to an underlying array

//construct array given its size.
public failsoftarray(int size)
{
a=new int[size];
}

// public property for array length
public int Length {
get {return a.Lenght;}
}


Next:

for(int i=0;i<(fs.length*2);i++)
fs[i]=i*10;

at this point the loop will run extra times but will not assign values to the underlying array,but will there be any use to set the error flag true each extra time a value is sent to the set accessor?
This is an example to show what can happen if you try to access elements that does not exist: the error flag is set to true.


for(int i=0;i<(fs.length*2);i++)
{
x=fs[i];
if(x!=-1) Console.Write(x+" ");
}


why are we assigning the values to x can`t we jst print fs[i]?

Yes, x is a temp variable that you do not need here.


for(int i=0;i<(fs.length*2);i++)
{
fs[i]=i*10;
if(fs.errflag)
Console.WriteLine("fs["+i+"]out of bound");
}


why are we assigning values to fs[i] again?doesn`t it already contain values?

Yes, they were already assign, but this is an example, on what happens, step by step, when you set an element of the collection to a value. errflag is unique for all elements of the collection. It indicates the success of failure of the last operation. Because in the first for loop there was an attempt to assign values to 10 elements, the flag remained set to true. In this second loop, each element is reassign, and the flag is tested after each operation. The first 5 iteration won't yield any error, but for the last 5 "fs[i] out of boud" will be printed.


for(int i=0;i<(fs.length*2);i++)
{
x=fs[i];
if(!fs.errflag) Console.Write(x+" ");
else Console.WriteLine("fs["+i+"] out of bound");
}


here again,why are we assigning vaues to x again??

Because this is a test of the get method of the index. Each time get or set are called, the flag is set or reset. As you can see the flag is tested here.

Hope things got clearer.

ironman
March 29th, 2005, 07:47 PM
Ya man!definately!Thanks!