Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda in C# extension method

Suppose I want to write an extension method to dump some data from a T[,] to a CSV:

public static void WriteCSVData<T>(this T[,] data, StreamWriter sw)
{
    for (int row = 0; row < data.GetLength(0); row++)
        for (int col = 0; col < data.GetLength(1); col++)
        {
            string s = data[row, col].ToString();

            if (s.Contains(","))
                sw.Write("\"" + s + "\"");
            else
                sw.Write(s);

            if (col < data.GetLength(1) - 1)
                sw.Write(",");
            else
                sw.WriteLine();
        }
}

which I could call with

using (StreamWriter sw = new StreamWriter("data.csv"))
  myData.WriteCSVData(sw);

but suppose myData is a Complex[,] and I want to write the magnitude of the complex number, not the full value. It would be handy if I could write:

using (StreamWriter sw = new StreamWriter("data.csv"))
  myData.WriteCSVData(sw, d => d.Magnitude);

but I'm not sure how to implement that in the extension method or if it's even possible.

like image 699
Ozzah Avatar asked Sep 15 '14 06:09

Ozzah


2 Answers

You can write an overload of your existing method like this:

public static void WriteCSVData<T, TValue>(this T[,] data, StreamWriter sw, 
    Func<T,TValue> func)
{
    for (int row = 0; row < data.GetLength(0); row++)
        for (int col = 0; col < data.GetLength(1); col++)
        {
            string s = func(data[row, col]).ToString();

            if (s.Contains(","))
                sw.Write("\"" + s + "\"");
            else
                sw.Write(s);

            if (col < data.GetLength(1) - 1)
                sw.Write(",");
            else
                sw.WriteLine();
        }
}

and use it the way you wanted:

using (StreamWriter sw = new StreamWriter("data.csv"))
    myData.WriteCSVData(sw, d => d.Magnitude);
like image 78
Eren Ersönmez Avatar answered Sep 22 '22 23:09

Eren Ersönmez


Define a delegate with parameter type T and return type string. Add a parameter to method WriteCSVData with type the delegate.

delegate string ExtractValueDelegate<T>(T obj);

public static void WriteCSVData<T>(this T[,] data,ExtractValueDelegte<T> extractor , StreamWriter sw) { ... }

// calling the method
 myData.WriteCSVData(sw, d => d.Magnitude.ToString());
like image 30
Sercan Avatar answered Sep 22 '22 23:09

Sercan