Click here to Skip to main content
15,885,278 members
Articles / Programming Languages / C#

Arithmetic in Generic Classes in C#

Rate me:
Please Sign up or sign in to vote.
4.65/5 (11 votes)
23 Feb 2009CC (ASA 2.5)8 min read 72.5K   556   27  
A discussion of doing arithmetic in generic classes and a small utility to make it easy.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace GenericArithmetic {
    public partial class E : GenericArithmetic.TemplateForm {
        public E() {
            InitializeComponent();
        }

    }

    /// <summary>
    /// An abstract base class that defines all of the mathematical operations we might want to do.
    /// </summary>
    public abstract class MathClass {
        public abstract MathClass Add(MathClass other);
        public abstract MathClass Subtract(MathClass other);
        public abstract MathClass Divide(MathClass other);
        public abstract MathClass Divide(int other);

        public static MathClass operator +(MathClass a, MathClass b) {
            return a.Add(b);
        }
        public static MathClass operator -(MathClass a, MathClass b) {
            return a.Subtract(b);
        }
        public static MathClass operator /(MathClass a, MathClass b) {
            return a.Divide(b);
        }

        public static MathClass operator /(MathClass a, int b) {
            return a.Divide(b);
        }
    }

    /// <summary>
    /// Then we can write our SummableList by placing a constraint on the type parameter.
    /// Now our summable list can only contain classes that derive from MathClass
    /// </summary>
    /// <typeparam name="T"></typeparam>

    public class SummableListC<T> : List<T> where T : MathClass, new() {

        public T Sum() {
            T result = new T();

            foreach (T thing in this) {
                result = (T)(result + thing);
            }

            return result;
        }

        public T Average() {
            return (T)(Sum() / Count);
        }
    }

    /// <summary>
    /// Then we have to create a new class derived from MathClass for any type that we might 
    /// want to use in our list.
    /// Here is the class that lets us use integers in our list.
    /// </summary>

    public class IntMathClass : MathClass {

        private int fValue = 0;

        public IntMathClass(int value) {
            fValue = value;
        }

        public IntMathClass() {
            fValue = 0;
        }

        public static implicit operator IntMathClass(int a) {
            return new IntMathClass(a);
        }

        public static implicit operator int(IntMathClass a) {
            return a.fValue;
        }

        public override MathClass Add(MathClass other) {
            if (other is IntMathClass) {
                return new IntMathClass(this.fValue + (IntMathClass)other);
            }

            return this;
        }

        public override MathClass Subtract(MathClass other) {
            if (other is IntMathClass) {
                return new IntMathClass(this.fValue - (IntMathClass)other);
            }

            return this;
        }

        public override MathClass Divide(MathClass other) {
            if (other is IntMathClass) {
                return new IntMathClass(this.fValue / (IntMathClass)other);
            }

            return this;
        }

        public override MathClass Divide(int other) {
            return new IntMathClass(this.fValue / other);
        }
    }

    /*
     * This method works, but is pretty limiting.
     * We can only use classes derived from MathClass.
     * Deriving from MathClass requires a relatively large amount of code.
     * Preexisting classes would have to be re-written to derive from MathClass because
     * there is no multiple inheritence in .Net
     * 
     * However, this does allow us to run the following in the Immediate Window
     * 
     * GenericArithmetic.SummableListC<GenericArithmetic.IntMathClass> list = new GenericArithmetic.SummableListC<GenericArithmetic.IntMathClass>();
     * 
     * list.Add(4);
     * list.Add(5);
     * list.Add(6);
     * list.Add(7);
     * 
     * ?list.Sum();
     * ?list.Average();
     */

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License


Written By
Software Developer (Senior) Coleman Insights
United States United States
Bill Fugina

Bill is a software developer at Coleman Insights.
He has been working professionally with C# and .Net since Visual Studio 2003 and for fun since the public beta. Before .Net, Bill worked with Delphi and Object Pascal.

Bill blogs at http://www.dogspots.com

Comments and Discussions