I'm relatively new to C#. I'm trying to use an IEnumerable
collection as an argument to a C# function, but I want to define the properties that I want to return as well.
Suppose I have a car IEnumerable
with properties such as color
and brand
. Each entry has a color and a brand, of course.
I'm trying to split the enumerable information on the function below.
Is something like this possible?
public string stringforeach(IEnumerable coll, <<color>>, <<brand>>)
{
string write = "";
int i = 0;
foreach (var element in coll)
{
write += string.Concat(i.ToString() + ";" + element.color+ ";" + element.bramd + "\n");
i++;
}
return write;
}
Use two separate features of C#:
Use generics so that the method can accept collections of a specific type with the compiler knowing about the specific type being used for a specific call of the method.
Use delegates as parameters to be able to pass functions (or lambda expressions) to specify which property of an object to access.
public string StringForeach<T>(IEnumerable<T> coll, Func<T, string> property1, Func<T, string> property2)
{
string write = "";
int i = 0;
foreach (var element in coll)
{
write += i + ";" + property1(element) + ";" + property2(element) + "\n";
i++;
}
return write;
}
Given the following Car class
public class Car
{
public string Color { get; set; }
public string Brand { get; set; }
}
you can call the method like this:
List<Car> cars = new List<Car>();
cars.Add(new Car { Color = "Red", Brand = "BMW" });
cars.Add(new Car { Color = "Black", Brand = "Mercedes" });
string text = StringForeach<Car>(cars, c => c.Color, c => c.Brand);
Some explanations:
public string StringForeach<T>(IEnumerable<T> coll, Func<T, string> property1, Func<T, string> property2)
This declares a generic method which can be called with a specific type T. It accepts three parameters:
IEnumerable<T> coll
: A collection of objects of type TFunc<T, string> property1
: A delegate to a function that accepts an argument of type T and returns a stringFunc<T, string> property2
: See above.When calling the method
string text = StringForeach<Car>(cars, c => c.Color, c => c.Brand);
we specify that we call the method with type T being the concrete type Car.
The lambda expression
c => c.Color
is a short form of writing a function delegate for this function:
string SomeFunc(Car c)
{
return c.Color;
}
The Bars
object from the API implements IEnumerable
. In order to convert this into the type IEnumerable<Bar>
, you can use this syntax:
IEnumerable bars = MarketData.GetBars();
IEnumerable<Bar> typedBars = bars.Cast<Bar>();
You can then call the method like this:
string text = StringForeach<Bar>(typedBars, c => c.OpenTime, c => c.Low);
Because the properties you want to use are not of type string directly, change the syntax like this:
public string StringForeach<T>(IEnumerable<T> coll, Func<T, object> property1, Func<T, object> property2)
{
string write = "";
int i = 0;
foreach (var element in coll)
{
write += i + ";" + property1(element) + ";" + property2(element) + "\n";
i++;
}
return write;
}
String conversion happens automatically.