Define Func in CSharp

In general, we can say Func is a special function which holds/handles many arguments. In other words we can say they can handles delegate, anonymous or generic type as a parameter. It encapsulates a method which can accept parameterized type.

The type of Func is a parameterized type. It can handle an anonymous method in a simpler way.

A typical syntax for Func is:

Func<T, TResult>

Referring msdn: http://msdn.microsoft.com/en-us/library/bb549151%28v=vs.110%29.aspx

Func is a part of System namespace and is defined as:

public delegate TResult Func<in T, out TResult>(T arg)

Where:
inT: Type of the parameter of the method to encapsulate
outTResult:Type of the return value of the method

Lets think some scenarios where someone wants to
– Format a number
– Make text to upper case

Now-a-days we have many options to do, we can choose in-build methods/functions or we can define own methods/functions, especially when we are delivering some kind of finished product to external users. These type of users would not aware and do not want to know the internal functionality but they want accurate result.

So, lets define our own methods in a simpler way:

  1. Define an Interface:IWithoutFuncType
namespace MyStuff
{
    public interface IWithoutFuncType
    {
        string ToUpper(string textToUpper);
        string FormatMe(int num);
        string ToSum(int num1, int num2);
    }
}
  1. Implement interface:IWithoutFuncType to class WithoutFuncType
using System;
using System.Globalization;

namespace MyStuff
{
    public class WithoutFuncType : IWithoutFuncType
    {
        public string ToUpper(string textToUpper)
        {
            return textToUpper.ToUpper(CultureInfo.InvariantCulture);
        }

        public string FormatMe(int num)
        {
            return String.Format("You entered {0}.", num);
        }

        public string ToSum(int num1, int num2)
        {
            return string.Format("Sum of {0} and {1} = {2}", num1, num2, num1 + num2);
        }
    }
}
  1. Compile above class and run in console:
using System;
using System.Collections.Generic;

namespace MyStuff
{
    class Program
    {
        static void Main(string[] args)
        {
            IWithoutFuncType withoutFuncType = new WithoutFuncType();

            Console.WriteLine(withoutFuncType.ToUpper("this is without func type"));
            Console.WriteLine();
            Console.WriteLine(withoutFuncType.FormatMe(109));
            Console.WriteLine(withoutFuncType.ToSum(101, 9));
            Console.ReadLine();
        }
    }
}

Output of above is very obvious, you will get things as defined. From here, our need to Func exists. Above, is a very simple example, there might be situations where we need to handle typical complex data and conditions for that do you want to write hundreds of a line to just getting a sum of two numbers or make it as UpperCase ? Frankly, I hate to write a method which would have more than- lines …

We can define following Func types for our basic operations, look at following snippet:

Func<string, string> _toUpper = st => st.ToUpper(CultureInfo.InvariantCulture);

Func<int, string> _formatMe = n => string.Format("You entered {0}", n);

Func<int, int, string> _toSum = (n, m) => string.Format("Sum of {0} and {1} = {2}", n, m, n + m);

Isn’t it so simple, looks like one-liner and these methods defined themselves by their names. Lets take first _toUpper Func, it is accepting string as parameter and returning string as a result and name is toUpper which tells, supply me, any string and I will return string in UpperCase.

Also, it is very issue to use above Func you just need to call its Invoke() method with desired parameters to fire/trigger. See bellow, snippet:

Console.WriteLine(_toUpper.Invoke(109));

Pretty easy, isn’t it 🙂

Lets think more complex areas you want performance and need to write a clean code. Due to scope of this article, I am not going to define more live examples, you can think-over, here is a complete snippet defining Func with a best typical usages:

  1. Define an interface IWithFuncType
using System.Collections.Generic;

namespace MyStuff
{
    public interface IWithFuncType
    {
        string FormatNumberAndMakeToUpper(int num);

        string GiveMeSumInDefinedFormat(int num1, int num2);

        string MakeMeInUpperCase(string stringToUpper);

        List<string> GiveMeFullNames(IEnumerable<FullName> suppliedNames);
    }
}
  1. Implement interface IWithFuncType with class WithFuncType
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;

namespace MyStuff
{
    public class WithFuncType : IWithFuncType
    {
        readonly Func<string, string> _toUpper = st => st.ToUpper(CultureInfo.InvariantCulture);
        readonly Func<int, string> _formatMe = n => string.Format("You entered {0}", n);
        readonly Func<int, int, string> _toSum = (n, m) => string.Format("Sum of {0} and {1} = {2}", n, m, n + m);

        public string FormatNumberAndMakeToUpper(int num)
        {
            return MakeMeInUpperCase(_formatMe.Invoke(num));
        }

        public string GiveMeSumInDefinedFormat(int num1, int num2)
        {
            return _toSum.Invoke(num1, num2);
        }

        public string MakeMeInUpperCase(string stringToUpper)
        {
            return _toUpper.Invoke(stringToUpper);
        }

        public List<string> GiveMeFullNames(IEnumerable<FullName> suppliedNames)
        {
            var fullNames = new List<string>();

            fullNames.AddRange(suppliedNames.Select(fullName => fullName.ToString(NameFormatter)));

            return fullNames;
        }

        private string NameFormatter(FullName stringToFormat)
        {
            var builder = new StringBuilder();

            builder.AppendFormat("{0} {1} {2}", stringToFormat.FirstName,
                stringToFormat.IsMiddleNameSupplied ? stringToFormat.MiddleName : "-", stringToFormat.LastName);

            return builder.ToString();
        }

    }

    public class FullName
    {
        public string FirstName { get; set; }
        public string MiddleName { get; set; }
        public string LastName { get; set; }

        public bool IsMiddleNameSupplied
        {
            get { return !string.IsNullOrEmpty(MiddleName); }
        }

        public string ToString(Func<FullName, string> formatter)
        {
            return formatter(this);
        }
    }
}
  1. Compile and run into Console:
using System;
using System.Collections.Generic;

namespace MyStuff
{
    class Program
    {
        static void Main(string[] args)
        {
             IWithFuncType withFuncType = new WithFuncType();
            Console.WriteLine(withFuncType.MakeMeInUpperCase("this is with func type"));
            Console.WriteLine();
            Console.WriteLine(withFuncType.FormatNumberAndMakeToUpper(109));
            Console.WriteLine(withFuncType.GiveMeSumInDefinedFormat(101, 9));

            //This is a typical example to use of Func Type

            var fullName = GetSomeFullNames();
            var names = withFuncType.GiveMeFullNames(fullName);
            Console.WriteLine();
            Console.WriteLine("A typical use of Func Type");
            Console.WriteLine();
            foreach (var name in names)
            {
                Console.WriteLine("Full Name: {0}", name);
            }
            Console.ReadLine();
        }

        private static void StuffWithFuncType()
        {
            IWithFuncType withFuncType = new WithFuncType();
            Console.WriteLine(withFuncType.MakeMeInUpperCase("this is with func type"));
            Console.WriteLine();
            Console.WriteLine(withFuncType.FormatNumberAndMakeToUpper(109));
            Console.WriteLine(withFuncType.GiveMeSumInDefinedFormat(101, 9));

            //This is a typical example to use of Func Type

            var fullName = GetSomeFullNames();
            var names = withFuncType.GiveMeFullNames(fullName);
            Console.WriteLine();
            Console.WriteLine("A typical use of Func Type");
            Console.WriteLine();
            foreach (var name in names)
            {
                Console.WriteLine("Full Name: {0}", name);
            }
        }

        private static List<FullName> GetSomeFullNames()
        {
            return new List<FullName>
            {
                new FullName
                {
                    FirstName = "Gaurav",
                    MiddleName = "Kumar",
                    LastName = "Arora"
                },

                new FullName
                {
                    FirstName = "Joseph",
                    MiddleName = "",
                    LastName = "Bulger"
                },
                new FullName
                {
                    FirstName = "Shuby",
                    MiddleName = "",
                    LastName = "Arora"
                }
            };
        }
    }
}

In above, user just need to provide a list of FullName and our program will return complete name with pre-defined format or business logic.

What to do next?
1. You can download complete example of FuncType from GitHub: https://github.com/garora/somestuff
2. Refer to msdn for more info: http://msdn.microsoft.com/en-us/library/bb549151%28v=vs.110%29.aspx

Note: If you find any issue with above article, please feel free to write your comments, also you can correct the same from GitHub project.

2 comments on “Define Func in CSharp”

Leave A Reply