8

We know that "Action, Func and Predicate are pre-defined Generic delegates. So as delegate they can point to functions with specified signature."

I have following data-access scenario in which Func<T,R> helps in avoiding a foreach loop in the calling method. The approach 2 doesn’t have looping. Here Func<T,R> helped to avoid loop.

What are the other scenarios for generic delegates in which it can save lots of lines of code?

REFERENCES

  1. Dynamically Composing Expression Predicates
  2. Advanced C#
  3. C#/.NET Little Wonders: The Predicate, Comparison, and Converter Generic Delegates
  4. Func vs. Action vs. Predicate
  5. What is Func, how and when is it used
  6. How can I pass in a func with a generic type parameter?

CODE

Approach 1

public class MyCommonDAL
{

    public static IEnumerable<IDataRecord> ExecuteQueryWithTextCommandType(string commandText, List<SqlParameter> commandParameters)
    {
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            using (SqlCommand command = new SqlCommand())
            {
                command.Connection = connection;
                command.CommandType = CommandType.Text;
                command.CommandText = commandText;
                command.CommandTimeout = 0;
                command.Parameters.AddRange(commandParameters.ToArray());

                connection.Open();
                using (var rdr = command.ExecuteReader())
                {
                    while (rdr.Read())
                    {
                        yield return rdr;
                    }
                    rdr.Close();
                }
            }
        }
    }

}


public class MyLogDAL
{
    public List<LogSeverityType> GetLogSeveritiesFirstApproach(LogSeverityType logSeverityType)
    {


        List<SqlParameter> commandParameters = new List<SqlParameter>()
                                                {
                                                    new SqlParameter {ParameterName = "@CreatedDateTime", 
                                                                      Value = logSeverityType.CreatedDateTime, 
                                                                      SqlDbType = SqlDbType.DateTime}
                                                };


        string commandText = @"SELECT * FROM dbo.LogSeverityType WHERE CreatedDateTime > @CreatedDateTime";
        var results = MyCommonDAL.ExecuteQueryWithTextCommandType(commandText, commandParameters);

        List<LogSeverityType> logSeverities = new List<LogSeverityType>();

 //LOOP
        foreach (IDataRecord rec in results)
        {
            LogSeverityType objLogSeverityType = LogSeverityType.LogSeverityTypeFactory(rec);
            logSeverities.Add(objLogSeverityType);
        }


        return logSeverities;
    }



}

Approach 2

    public class MyCommonDAL
    {

        public static IEnumerable<T> ExecuteQueryGenericApproach<T>(string commandText, List<SqlParameter> commandParameters, Func<IDataRecord, T> factoryMethod)
        {

            //Action, Func and Predicate are pre-defined Generic delegates.
            //So as delegate they can point to functions with specified signature.

            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                using (SqlCommand command = new SqlCommand())
                {
                    command.Connection = connection;
                    command.CommandType = CommandType.Text;
                    command.CommandText = commandText;
                    command.CommandTimeout = 0;
                    command.Parameters.AddRange(commandParameters.ToArray());

                    connection.Open();
                    using (var rdr = command.ExecuteReader())
                    {
                        while (rdr.Read())
                        {
                            yield return factoryMethod(rdr);
                        }
                        rdr.Close();
                    }
                }
            }
        }


    }


    public class MyLogDAL
    {

        public List<LogSeverityType> GetLogSeveritiesSecondApproach(LogSeverityType logSeverityType)
        {


            List<SqlParameter> commandParameters = new List<SqlParameter>()
                                                    {
                                                        new SqlParameter {ParameterName = "@CreatedDateTime", 
                                                                          Value = logSeverityType.CreatedDateTime, 
                                                                          SqlDbType = SqlDbType.DateTime}
                                                    };


            string commandText = @"SELECT * FROM dbo.LogSeverityType WHERE CreatedDateTime > @CreatedDateTime";
            //var results = MyCommonDAL.ExecuteQueryWithTextCommandType(commandText, commandParameters);

            IEnumerable<LogSeverityType> logSeverities = MyCommonDAL.ExecuteQueryGenericApproach<LogSeverityType>(commandText, commandParameters, LogSeverityType.LogSeverityTypeFactory);

            //foreach (IDataRecord rec in results)
            //{
            //    LogSeverityType objLogSeverityType = LogSeverityType.LogSeverityTypeFactory(rec);
            //    logSeverities.Add(objLogSeverityType);
            //}


            return logSeverities.ToList();
        }


    }

Other Code Required

    public class LogSeverityType
    {
        public int LogSeverityTypeID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public DateTime CreatedDateTime { get; set; }

        public static LogSeverityType LogSeverityTypeFactory(IDataRecord record)
        {
            return new LogSeverityType
            {
                LogSeverityTypeID = (int)record[0],
                Name = (string) record[1],
                Description = (string)record[2],
                CreatedDateTime = (DateTime) record[3]
            };
        }
    }

        static void Main(string[] args)
        {
            MyLogDAL logDAL = new MyLogDAL();
            LogSeverityType logSeverityType = new LogSeverityType();
            logSeverityType.CreatedDateTime = Convert.ToDateTime("1/1/2000");

            List<LogSeverityType> logSeverities = logDAL.GetLogSeveritiesSecondApproach(logSeverityType);
        }
Community
  • 1
  • 1
LCJ
  • 22,196
  • 67
  • 260
  • 418
  • 1
    "What are the other most significant 5 usage scenarios for generic delegates?" - surely that is subjective? – Nathan Dec 19 '13 at 12:38
  • 1
    Sure, no question about that - but should probably go over on http://programmers.stackexchange.com/? – Nathan Dec 19 '13 at 12:42
  • 1
    @Nathan: I think even [programmers.se] would reject this one. It's pure opinion and nothing else. – John Saunders Dec 19 '13 at 12:45
  • @John: I see, thanks :) Lijo, maybe consider rephrasing it to something more specific? – Nathan Dec 19 '13 at 12:49
  • References - [USING STRATEGY PATTERN AND DELEGATES INSTEAD OF SWITCH STATEMENT](http://www.namedquery.com/strategy-pattern-and-delegates) and [How to Improve Code Reusability Using C# Delegates](http://blog.velir.com/index.php/2011/07/14/how-to-improve-code-reusability-using-c-delegates/) – LCJ Dec 20 '13 at 14:40

1 Answers1

1

I use generic delegates when parsing / finding nodes in XML / HTML documents, and assigning the values to properties. I wrote a blog post about it, which shows refactoring the code to pass in a generic delegate, and how much code was removed.

harriyott
  • 10,505
  • 10
  • 64
  • 103