Dot Net Perls

Math.Max and Min for Bounds-Checking - C#

by Sam Allen

Problem

Improve the style of your code that calculates integer bounds. Often in your algorithms you need to test if an integer < 0, because that must be special-cased. Test for these conditions with less code.

Solution: C# and Math class

One style many projects use is the integer maximum and minimum methods or macros. These can be rewritten with greater consistency using Math.Min and Math.Max. First, here's the before code. If you are like me, you have lots of code like it:

using System;

class Program
{
    static int[] _array = new int[]
    {
        1,
        2,
        5,
        6,
        7
    };

    static void Main()
    {
        // Get 1 place from end.
        int i = GetLastIndex(1);
        Console.WriteLine(i); // "6"

        // Get 3 places from end.
        i = GetLastIndex(3);
        Console.WriteLine(i); // "2"

        // Get 10 places from end. Will not throw exception.
        i = GetLastIndex(10);
        Console.WriteLine(i); // "1"
    }

    static int GetLastIndex(int length)
    {
        //
        // A.
        //
        int start = _array.Length - length - 1;
        //
        // B.
        //
        if (start < 0)
        {
            return _array[0];
        }
        else
        {
            return _array[start];
        }
    }
}

Question: why test against zero?

Because using a negative number on the indexer will throw an exception. What you will get is an IndexOutOfRangeException, which Microsoft describes like this:

"An IndexOutOfRangeException exception is thrown when an attempt is made to access an element of an array or collection with an index that is outside the bounds of the array or less than zero." [Troubleshooting Exceptions: IndexOutOfRangeException - MSDN]

Question: how can I improve the range-checking?

With Math.Max. In part B in the code above, you have 9 lines of code. You can replace that with one line of code using Math.Max. What we do is take the maximum of zero and the value. That way, the result will never be less than zero.

using System;

class Program
{
    static int[] _array = new int[]
    {
        1,
        2,
        5,
        6,
        7
    };

    static void Main()
    {
        // Get 1 place from end.
        int i = GetLastIndex(1);
        Console.WriteLine(i); // "6"

        // Get 3 places from end.
        i = GetLastIndex(3);
        Console.WriteLine(i); // "2"

        // Get 10 places from end. Will not throw exception.
        i = GetLastIndex(10);
        Console.WriteLine(i); // "1"
    }

    static int GetLastIndex(int length)
    {
        //
        // A.
        //
        int start = _array.Length - length - 1;
        //
        // B.
        //
        start = Math.Max(0, start);
        return _array[start];
    }
}

Question: what else should I know?

I have benchmarked Math.Min and Math.Max and they are no different from typing the 9 lines yourself. The only difference is that your code is shorter, simpler to read, and less prone to typos.

Question: why is this important?

Because you can impress your interviewers with it. Really, it just makes your code shorter, more precise, and more maintainable. Here are a couple more examples.

Before - "if"After - Math.Max
using System; class Program { static void Main() { // // 1. // Constrain indexes with if. // int a = 4; if (a < 0) { Console.WriteLine(0); } else { Console.WriteLine(a); } } }using System; class Program { static void Main() { // // 2. // Constrain indexes with Math.Max. // int a = 4; Console.WriteLine(Math.Max(0, a)); } }
• 6 lines for testing• 1 line for testing

The following table shows how you can cap values at a certain number using Math.Min. It works equally well as the method before.

Before - "if"After - Math.Min
using System; class Program { static void Main() { // // Make sure it isn't > 10. // int b = 15; if (b > 10) { b = 10; } Console.WriteLine(b); } }using System; class Program { static void Main() { // // Make sure it isn't > 10. // int b = 15; Console.WriteLine(Math.Min(10, b)); } }
• 3 lines for conditional• 1 line for conditional

Summary: using bounds-checking

Clarify your bounds-checking, simplify it, and impress interviewers with Math.Min() and Math.Max(). There are many other methods on the Math static class, most of which can have similar effects on code quality.

Dot Net Perls
About
Sitemap
Source code
RSS
Integers
Use int.Parse for Integer Conversion
Random Number Generator Use
Numeric Types and Casts
int Max and Min Constants
Math.Max and Min for Bounds-Checking
Recent
Pi
NGEN Installer Class
List Element Equality
DateTime Tips and Tricks
Remove HTML Tags From String
© 2008 Sam Allen. All rights reserved.