Comparing Curve classes and delegates

The classes that inherit from Curve on the one hand, and the Func<T, TResult> delegate on the other, both represent mathematical functions of one real parameter that return a real number. You can create a Func<T, TResult> from a Curve by encapsulating the curve's ValueAt method. You can create a Curve from a Func<T, TResult> using the GeneralCurve class, which takes a Func<T, TResult> delegate in its constructor. They are different in nature, however.

A Curve object represents a function in the mathematical sense. Very often, a specific type of function has special properties that enable many calculations to be performed more efficiently. For example: polynomials are easy to integrate and differentiate. To use a numerical integration algorithm for polynomials would be inefficient.

A Func<T, TResult> delegate encapsulates only the calculation of the value of the function. This is sufficient for most applications. The methods in the FunctionMath all use a Func<T, TResult> delegate. These operations can be controlled to a great degree. Note that the Curve class has methods corresponding to many of these methods, but the degree of control is much more limited.

In other words: a Curve object focuses on the mathematical function as a mathematical object, and the specific mathematical properties and relationships of a particular type of curve. A Func<T, TResult> delegate isolates the primary purpose of a mathematical function - to calculate a return value for a given argument - into a simple data type. This allows it to fit easily into any of a number of more complex procedures for solving numerical problems.

In summary:

  • If you work with a mathematical function for which a specialized Curve type exists, it is usually better to use the Curve type.

  • In other situations it is more of a trade-off between the simplicity of the direct abstraction of a mathematical function versus the degree of control you have over the calculation of derivatives, integrals and zeros.