#1,118 – foreach Works with Iterator Returned by yield

You can use the yield keyword in a method to implement an iterator.  The method in which it is defined returns an IEnumerable or IEnumerator.  The resulting iterator can be consumed using the foreach statement.

Below is an example of a method that returns an IEnumerable<T> which can then be iterated upon using a foreach statement.

        static IEnumerable<Dog> DogsWithKids(IEnumerable<Dog> dogList)
        {
            foreach (Dog d in dogList)
            {
                yield return d;
                yield return new Dog(d.Name + " Jr.",
                                     Math.Max(d.Age - 3, 1));
            }
        }

        static void Main(string[] args)
        {
            List<Dog> myDogs = new List<Dog>
                {
                    new Dog {Name = "Kirby", Age = 15},
                    new Dog {Name = "Ruby", Age = 2}
                };

            // Iterate through dogs w/offsprings
            foreach (Dog d in DogsWithKids(myDogs))
                Console.WriteLine(d);

            Console.ReadLine();
        }

The result is a sequence with twice as many elements as the original List<T>.

1118-001

#1,117 – foreach Requires IEnumerable Implementation

The foreach statement works on an object that implements IEnumerable<T> or IEnumerable.  It also works on an object whose type has a public GetEnumerator method that returns an IEnumerator<T> or IEnumerator.

Below, we’ve defined a new class that implements IEnumerable<T>.

    public class DogPack : IEnumerable<Dog>
    {
        private List<Dog> thePack;

        public DogPack()
        {
            thePack = new List<Dog>();
        }

        public void Add(Dog d)
        {
            thePack.Add(d);
        }

        // Remove arbitrary dog
        public void Cull()
        {
            if (thePack.Count == 0)
                return;

            if (thePack.Count == 1)
                thePack.RemoveAt(0);
            else
            {
                Random rnd1 = new Random();
                int indRemove = rnd1.Next(thePack.Count);
                thePack.RemoveAt(indRemove);
            }
        }

        // IEnumerable<T> implementation

        public IEnumerator<Dog> GetEnumerator()
        {
            return thePack.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

We can now use foreach to iterate on an instance of this class.

            DogPack pack = new DogPack();
            pack.Add(new Dog("Lassie", 8));
            pack.Add(new Dog("Shep", 12));
            pack.Add(new Dog("Kirby", 10));
            pack.Add(new Dog("Jack", 15));
            pack.Cull();

            // Who's left?
            foreach (Dog d in pack)
                Console.WriteLine(d);

1117-001

#1,116 – Iterating Through a String Using the foreach Statement

You can iterate through the individual characters in a string using the foreach statement.  The iteration variable is of type char and is set consecutively to each character within the string as the foreach statement executes.

            string secret = "Kint is Keyser Soze";

            StringBuilder sbObfuscate = new StringBuilder();

            foreach (char c in secret)
                sbObfuscate.Append((char)(c + 3));

            Console.WriteLine(sbObfuscate);

1116-001

#1,115 – Iterating Through a Collection Using the foreach Statement

In the same way that you can iterate through an array using foreach, you can iterate through the elements of a collection one at a time.  You do this by writing a loop–a block of code that is executed more than once, executing once for each element in the collection. This is done using the C# foreach statement.

The foreach statement declares a variable local to the loop of the same type of the elements in the collection.  This variable takes on the value of each element in the collection.

            List<Dog> myDogs = new List<Dog>
            {
                new Dog {Name = "Kirby", Age = 15},
                new Dog {Name = "Jack", Age = 17},
                new Dog {Name = "Ruby", Age = 2}
            };

            // Output using overridden ToString() method
            foreach (Dog d in myDogs)
                Console.WriteLine(d);
1115-001

#1,114 – Don’t Use Shift Operators to Do Multiplication

When you use the shift operators on integer-based values, you effectively multiply a number by two when you do a left shift by one bit and divide a number by two when you do a right shift by one bit.

In years past, you’d sometimes hear a recommendation that you should prefer using the shift operators over multiplicative operators because the shift operators were faster.

With modern optimizing compilers, you should no longer worry about this level of optimization and performance.  If you need to multiply a number by a power of two, you should express your intent by using the multiplicative operators.  (E.g. “* 2” or “* 4”).  The compiler will figure out that fastest way to accomplish this.

#1,113 – Addition of Integers Using Twos Complement

The primary benefit of using twos complement to represent signed integers is that addition and subtraction work the same, whether the number is positive or negative.

Below is an example, showing how we add the value -2 to the value +5, yielding a result of +3.  (Assuming that both values are stored as 16-bit integers).  The carry bits are shown in the top line.  We discard the final carry bit that results from adding the leftmost two bits.

1113-001

#1,112 – How Integers Are Stored in .NET

Integer values in .NET are stored in memory as described below.  The examples below use a 2-byte short data type as an example.

A value of zero is stored by setting every bit in the storage location to zero.

Positive values are stored directly as their corresponding binary number.

1112-001

The maximum possible integer value has all bits set to 1 except for the leftmost.  So Max = 2^(n-1) – 1, where n is the total number of bits.

Negative integer values are stored using a two’s complement representation, calculated by starting with the bit pattern for the corresponding positive number, negating all of the bits, and then adding 1 to the result.

1112-002

The minimum possible integer value (largest negative value) has only the leftmost bit set to 1.  So Min = -(2^(n-1)), where n is the total number of bits.

 

 

#1,111 – Converting an Integer to a String in a Different Base

You can convert an integer-based value to a string using the ToString method on the integer.  This results in a string representing the integer as a base 10 number.

            int i = 42;
            // ToString() called implicitly
            Console.WriteLine(i);  // base 10

1111-001

You can also convert integer-based values to strings that represent the number in base 2 (binary), 8 (octal), or 16 (hexadecimal).  You use the Convert.ToString method, passing it the number to convert and the base.

            int i = 42;
            int i2 = 1964;
            int i3 = -128;

            Console.WriteLine("{0} dec, {1} hex, {2} oct, {3} bin",
                i,
                Convert.ToString(i, 16),
                Convert.ToString(i, 8),
                Convert.ToString(i, 2));

            Console.WriteLine("{0} dec, {1} hex, {2} oct, {3} bin",
                i2,
                Convert.ToString(i2, 16),
                Convert.ToString(i2, 8),
                Convert.ToString(i2, 2));

            Console.WriteLine("{0} dec, {1} hex, {2} oct, {3} bin",
                i3,
                Convert.ToString(i3, 16),
                Convert.ToString(i3, 8),
                Convert.ToString(i3, 2));

1111-002

#1,110 – The Bitwise Exclusive OR Operator

You can use the ^ operator to do a bitwise exclusive OR (“XOR”) operation between two integer-based values.

An exclusive OR operation is applied to two different bits, returning true if exactly one of the input bits is true.  Here is a truth table showing the output value for all possible input combinations.

  • 0 ^ 0 = 0
  • 0 ^ 1 = 1
  • 1 ^ 0 = 1
  • 1 ^ 1 = 0

You can use the ^ operator on two arbitrary integer values as shown below.  The operation is applied to the two integer values, one bit at a time.

            int n1 = 12;
            int n2 = 10;
            int result = n1 ^ n2;
            Console.WriteLine("{0} ^ {1} = {2}", n1, n2, result);

1110-001
It may help to use hex notation in order to better understand how the exclusive OR operation works on each bit.

            int n1 = 0xC;  // 12 (dec) or 1100 (bin)
            int n2 = 0xA;  // 10 (dec) or 1010 (bin)

            // Result = 0110 bin (6 dec)
            int result = n1 ^ n2;

1110-002

#1,109 – The Bitwise NOT Operator

You can use the ~ operator to do a bitwise NOT operation on an integer-based value.

A NOT operation is applied to a single input bit, returning true if the input bit is false, or false if it is true.  The NOT operator “flips” or “negates” the input bit.  Here is a truth table showing the output value for the possible input values.

  • ~0  = 1
  • ~1 = 0

You can use the ~ operator on an arbitrary integer value as shown below.  The NOT operation will be applied to the integer value, one bit at a time.

            int n = 5;
            int result = ~n;
            Console.WriteLine("~{0} = {1}", n, result);

1109-001
It may help to use hex notation in order to better understand how the NOT operation works on each bit.

            int n = 0x00000005;
            int result = ~n;
            Console.WriteLine(  "~{0:X8} = {1:X8}", n, result);

1109-002

1109-003