#1,150 – Generic Delegate Type as Parameter

You can use a generic delegate type as a parameter to a method.

Suppose that we have the following type:

        public delegate T Merger<T>(T thing1, T thing2);

We can now create a method that takes a constructed version of this type as a parameter.  We could then call the method as shown in the Main method.

        static void MergeInts(Merger<int> intMerger, int n1, int n2)
        {
            int result = intMerger(n1, n2);
        }

        public static int Add(int n1, int n2)
        {
            return n1 + n2;
        }

        static void Main(string[] args)
        {
            MergeInts(Add, 5, 6);
        }

We could also define a generic method that has a generic delegate parameter.

        static void MergeSomething<T>(Merger<T> someMerger, T thing1, T thing2)
        {
            T result = someMerger(thing1, thing2);
        }

We can then call this method as follows:

        public static Dog Breed(Dog mama, Dog papa)
        {
                return new Dog(mama.Name + papa.Name);
        }

        static void Main(string[] args)
        {
            MergeSomething(Add, 5, 6);

            Dog dog1 = new Dog("Lassie");
            Dog dog2 = new Dog("Spuds");
            MergeSomething(Breed, dog1, dog2);
        }
Advertisements

#1,149 – Generic Delegate Types

A delegate type can be generic.  Consider the following delegate type:

        public delegate T Merger<T>(T thing1, T thing2);

This delegate type defines a pattern for methods that take two parameters of a particular type and returns the same type.  Below are a couple examples of methods whose signature matches this delegate type.  (Methods are only static so that we can call them from another static method).

        public static int Add(int n1, int n2)
        {
            return n1 + n2;
        }

        public static Dog Breed(Dog mama, Dog papa)
        {
                return new Dog(mama.Name + papa.Name);
        }

We can now declare Merger<T> instances that refer to these methods as follows:

            Merger<int> adder = Add;
            Merger<Dog> breeder = Breed;

#1,128 – Disable a Compile-Time Warning for Entire Project

You can use #pragma warning to selectively disable certain warnings that occur when compiling your code.  When #pragma warning disable is encountered, the specified warning will be disabled for the current file, from the point where the pragma appears until the end of the file, or until a #pragma warning restore is encountered for the same warning.

If you want to disable a particular warning for all files compiled in a project, rather than just within a single file, you can add the warning number to the Suppress warnings field on the Build tab in the project properties window.  This will suppress the specified warning for the entire project.

1128-001

1128-002

#1,127 – Where to Find Compiler Warning Numbers

You can use #pragma warning to selectively disable certain warnings that occur when compiling your code.

The #pragma warning line requires knowing the specific warning number, which is not displayed in the list of warnings on the Error List tab.

1127-001

To find the warning number, you need to switch to the Output tab and look at the full text of the warning.  In the example below, we see that the warning about an event that is never used is warning #67.

1127-002

Once you know the warning number, you can use it with a #pragma warning.

#pragma warning disable 67
        public event EventHandler CanBarkChanged;
#pragma warning restore 67

#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,106 – Using the Logical Exclusive OR Operator

You can use the exclusive OR (^) operator to do a bitwise exclusive OR operation.  The operands in this case are integer-based types.

You can also use the exclusive OR operator on boolean operands.  The result of the operation is true if exactly one of the operands (but not both) is true.

  • false ^ false => false
  • false ^ true => true
  • true ^ false => true
  • true ^ true => false
            bool itsThursday = DateTime.Now.DayOfWeek == DayOfWeek.Thursday;
            bool itsMay = DateTime.Now.Month == 5;

            // Wear red shirt in May, wear red shirt every Thursday,
            // but don't wear red shirt on Thursdays in May
            bool wearRedShirt = itsThursday ^ itsMay;

            Console.WriteLine("Thursday:{0}, May:{1}, RedShirt:{2}", itsThursday, itsMay, wearRedShirt);

1106-001