You have a lot of basic C# questions here. Honestly the best thing to do is read the docs for C# as they explain everything. I have included links to the appropriate topics.
yield return make(reader)
is an iterator (docs). In the special case of a method that returns IEnumerable<T>
, C# allows you to use iterator syntax to return 1 item at a time from the method rather than stuffing the results into a temporary collection. The compiler generates an IEnumerable<T>
wrapper that keeps calling your method like a coroutine until the method finishes executing. Each time yield
is called the value is returned as the next "result" from the method. When the method is called by the generated code the next time it resumes from there (rather than from the beginning like a normal method). This is an advanced concept and honestly you don't need to understand how it works to use it. The closest equivalent code without an iterator would look something like this).
public IEnumerable<T> Read<T>(string sql, Func<IDataReader, T> make, params object[] parms)
{
var results = new List<T>();
using (var connection = CreateConnection())
{
using (var command = CreateCommand(CommandType.Text, sql, connection, parms))
{
command.CommandTimeout = dataBaseSettings.ReadCommandTimeout;
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
results.Add(make(reader));
}
}
}
};
return results;
}
Func<IDataReader, T>
is a delegate (docs). In other languages they are called function objects. It allows you to treat a function as data and pass it to other functions or store in variables. Func
is a built in function type that says "any method that accepts an IDataReader
and returns T
can be used here". You pass in the function (with matching signature) you want called and each time through the while loop it calls your function, passing it the reader
variable's current value. Delegates are heavily used in LINQ and programming in general these days.
IEnumerable<string> results = Read<string>("my sql", GetAString);
IEnumerable<string> results2 = Read<string>("my sql", GetADifferentString);
string GetAString ( IDataReader reader )
{
return "A String";
}
string GetADIfferentString ( IDataReader reader )
{
return "A Different String";
}
IDataReader
(docs) is an interface that allows you to enumerate the results of a database result set. Each time you read the next "row" the reader contains that row's data. In your example code the method that you pass to the call gets the reader and presumably retrieves the data from the current row. It is called for each row because of the while loop. For each row it is returning the results of that row. The method doesn't know what it'll return so it uses a generic method (docs) to represent the data that is being created as a type called T
. This makes the code work with any type.
IEnumerable<Product> products = Read<Product>("my sql", ReadProduct);
IEnumerable<Order> orders = Read<Order>("my sql", ReadOrder);
Product ReadProduct ( IDataReader reader )
{
//return a Product from the current row's data
}
Order ReadOrder ( IDataReader reader )
{
//return an Order from the current row's data
}