Thursday, July 23, 2015

.Equals != == ...?

Equality!


Confusing title huh? I found out recently that .Equals() doesn't always behave the same as ==. More specifically, I was trying to compare an Int32 (int) to an Int64 (long). It was a bit more complicated than that really, I needed to find items in a list of complicated objects that matched (just by this number) complicated objects of another type in another list, and I kept coming up with no matches. I knew I should have some, but the comparison was coming up false for everything! I had a check kind of like this:
return SomeObj.SomeIntProp.Equals(SomeOtherObj.SomeLongProp);

I didn't realize at the time I initially coded it that one was an Int32 and the other an Int64, but I didn't really think it mattered anyways. So I changed it to something like this just for giggles:
return SomeObj.SomeIntProp == SomeOtherObj.SomeLongProp;

And sure enough, my code was now getting back the correct number of true results that I thought it should! Just so you know, the reason is this: there are 2 overloaded versions of Int32.Equals. One accepts an int parameter (Int32), and the other an Object parameter. If you are comparing int to int, then you'll call the first method which checks that the numbers are the same. If you call .Equals and you don't pass an Int32 value, then you will end up using the 2nd version of the method which accepts an Object parameter and always returns false if the value isn't in fact an Int32 or something with an implicit conversion to Int32. No such implicit conversion exists for Int64 to Int32. Boom!

Here's a sample console app you can run to see this in action:

using System;

namespace BlogEquals
{
    class Program
    {
        static void Main(string[] args)
        {
            int int1 = 34;
            long long1 = 34;
            Console.WriteLine("int1 == long1: " + (int1 == long1).ToString());
            Console.WriteLine("int1.Equals(long1): " + int1.Equals(long1).ToString());
            Console.ReadKey();
        }
    }
}


 The output is this:


What's Next?

See for yourself what happens if the right-side of the comparison is an Int16...can you explain the result?

Resources

Int32.Equals

Thursday, July 9, 2015

C# Anonymous Functions

Intro

Anonymous Functions: Things that activist hacker group does when they go into the potty room. Darn, I keep forgetting this is a programming blog! OK in this case an Anonymous Function is an "inline statement or expression that can be used wherever a delegate type is expected." (1). In layman's terms, rather than supplying a fully-defined function to a delegate, you can create an anonymous function within your normal code and use that. It's hard to explain, so let's see it in action.



Code Samples in VS2013, .Net 4.5.

Simple Use Case



using System;

namespace BlogAnonymousFunction
{
    public class Thingy
    {
        public string DoAThing(int val1, int val2, Func preProcessor = null)
        {
            int val3 = -1;
            if (preProcessor != null)
                val3 = preProcessor(val1, val2);
            return String.Format("val1:{0}, val2:{1}, val3: {2}", val1, val2, val3);
        }
    }
}


using System;

namespace BlogAnonymousFunction
{
    class Program
    {
        static void Main(string[] args)
        {
            var thingy = new Thingy();
            var result = thingy.DoAThing(24, 42, null);
            Console.WriteLine(result);
            result = thingy.DoAThing(24, 42, new Func((val1, val2) => val1 + val2));
            Console.WriteLine(result);
            Console.ReadKey();
        }
    }
}



A simple example to be certain. Our class Thingy has a single method DoAThing that accepts a function as a parameter. If the user passes in a value for this nullable function we will call it and set it to our 3rd value.

In the Main method we call DoAThing twice. First we call it once passing in a null function parameter. In the second call we pass in an anonymous function that adds the first and 2nd parameter, returning the result. You can see the results of our two function calls in the output window screenshot below.


Cool huh? Simple too, but it does take a few repetitions to get used to the odd syntax. Enjoy!

What's Next?

You can also do generic methods (no return type), you can create variables that reference a generic function/method, and more! Search on teh webs, you'll find plenty.

Resources

(1) Anonymous Functions
The Generic Func Delegates