user9704250
user9704250

Reputation:

pass lambda as a delegate to method

Im new in c# and I'm very confused over delegates. I know we should use them once we need to pass same signatures methods with different condition to a method.

I have a class:

public class Turbines
{
    public string Turname { get; set; }
    public double TurID { get; set; }

    public double Production { get; set; }

    public double Availability { get; set; }
}

I initialize this class:

List<Turbines> newTur = new List<Turbines>
{
    new Turbines { Turname="inUK", TurID=1245, Production=1452.22, Availability=52.12 },
    new Turbines { Turname="InUS", TurID=125, Production=1052.22, Availability=92.12 }
};

Now if I want to get Turnames with avalability>90% and next time Turnames with Production>1300, I can have a method and pass a delegate to it.

Can anyone tell me how to create a method and delegate?

Upvotes: 1

Views: 6787

Answers (5)

WaughWaugh
WaughWaugh

Reputation: 1032

In this case, you want to get 2 different results from the same collection (List) at 2 different times. The most basic way to do this would be define methods within that collection which would return you results, ex - one method which returns you results whose availability > 90% and another whose production > 1300. But by doing those, you are losing the dynamic nature of the request and making the collection heavy with methods - meaning everytime you need to change this criteria you need to modify the collection and add a new method.

To solve this problem, we have delegates - which said simply works like a function pointer. So, basically instead of writing new methods in the container, you are passing a piece of code as an object which determines which elements to select out of your collection. This approach is called "Inversion of Control".

So, here for availability, you call List.Where and pass it a function which tells it whether to include a particular Turbines object or not.

Func<Turbines, bool> availabilityFunc = delegate (Turbines t)
{
    return t.Availability > 90;
};
var result = newTur.Where(availabilityFunc);

The Where method is a filtering method which selects certain elements in the container based on the predicate which is passed. Here, the predicate is the Func type delegate - which basically is a function object within which I have encapsulated the selection logic.

Now instead of doing all this, you can simply pass a lambda expression as a shortcut.

var result = newTur.Where( t => t.Availability > 90; );

Upvotes: 0

bommelding
bommelding

Reputation: 3037

Delegates are a way to pass methods (including lambdas) as parameters:

   var selection = MyFilter( newTur , t => t.Availability > 90);


IENumerable<Turbines> MyFilter(IENumerable<Turbines> source, Func<Turbines, bool> filter)
{
   return source.Where(filter);
}

Note that things become slightly more readable when you drop the s from Turbines. An object is a single Turbine.

And a lambda is just a way to write an in-line function. You can also call MyFilter like this:

 var selection2 = MyFilter( newTur , ProductionOver1300);


bool ProductionOver1300(Turbines t)  // matches  Func<Turbines, bool> 
{
   return t.Production > 1300;
} 

The syntax is tricky, bool b = ProductionOver1300(aTurbine) is a nomal function call. Leave out the parameters to get a delegate: Func<Turbines, bool> f = ProductionOver1300; . f is now a delegate variable and you can do bool b = f(aTurbine);

Upvotes: 3

Sweeper
Sweeper

Reputation: 271420

You need the Predicate<Turbine> delegate. This delegate represents a method with the following signature:

bool Method(Turbine turbine)

You should write a method like this:

public List<Turbine> GetTurbines(Predicate<Turbine> predicate) {
    var list = new List<Turbine>();
   foreach (var turbine in newTur) {
       if (predicate(turbine)) {
           list.Add(turbine);
       }
   }
   return list;
}

Note the part if (predicate(turbine)), there I am basically calling the method that is passed in. If the method returns true, I add it to the list.

So you could pass a method like this into GetTurbines to get all the turbines with availability over 90:

bool Over90Availability(Turbine turbine) {
   return turbine.Availability > 90;
}
// ...
var list = GetTurbines(Over90Availability);

You can rewrite the method with a lambda expression:

var list = GetTurbines(turbine => turbine.Availability > 90);

The word turbine before the => is the parameter name. Everything after the => is the value you return.

Hope you understand how this works now.

In fact, you have just reinvented the wheel by creating GetTurbine. There is an extension method called Where in System.Linq.Enumerable that is basically the same thing:

var list = newTur.Where(turbine => turbine.Availability > 90).ToList();

Upvotes: 1

Tao G&#243;mez Gil
Tao G&#243;mez Gil

Reputation: 2705

It's not entirely clear what you are asking, so I will try to explain some basic concepts.

First of all, since you have a List<Turbines> and List<T> implements IEnumerable<T>, you can use the .Where extension method. This method acts on an IEnumerable<TSource>, and takes as argument a predicate with the signature Func<TSource, bool>. You can pass this argument in several ways, the two more common being 1) with a lambda and 2) with a classic method:

public class YourClass
{
    public void YourMethod()
    {
        List<Turbines> newTur = new List<Turbines>
        {
            new Turbines { Turname = "inUK", TurID = 1245, Production = 1452.22, Availability = 52.12 },
            new Turbines { Turname = "InUS", TurID = 125, Production = 1052.22, Availability = 92.12 }
        };

        // 1) passing filter as a lambda
        IEnumerable<Turbines> filteredListWithLambda = newTur.Where(t => t.Availability > 90.0 && t.Production > 1300);

        // 2) passing filter as a method
        IEnumerable<Turbines> filteredListWithMethod = newTur.Where(Filter);
    }

    private bool Filter(Turbines turbines)
    {
        return turbines.Availability > 90.0 && turbines.Production > 1300;
    }
}

If you want to change the values of your filter, you will have have to receive in YourMethod these values, and plug them in the filter, like this:

public class YourClass
{
    public void YourMethod(double availability, int production)
    {
        List<Turbines> newTur = new List<Turbines>
        {
            new Turbines { Turname = "inUK", TurID = 1245, Production = 1452.22, Availability = 52.12 },
            new Turbines { Turname = "InUS", TurID = 125, Production = 1052.22, Availability = 92.12 }
        };

        IEnumerable<Turbines> filteredListWithLambda = newTur.Where(t => t.Availability > availability && t.Production > production);
    }
}

Upvotes: 0

mk Mughal
mk Mughal

Reputation: 298

Just simply apply this piece of code

var result = newTur.Where(each => each.Availability > 90 && each.Turnames > 1300);

Upvotes: 0

Related Questions