Когда параметры в лямбда-выражении предпочтительнее? - PullRequest
1 голос
/ 02 декабря 2011

Это довольно странный вопрос, но он возник на днях и заставил меня задуматься.

Когда предпочтительнее использовать лямбда-выражения в этой форме? "(X => x.) "verse". (() => obj.Wh независимо) ".

Рассмотрим следующие методы расширения.

public static class ExtensionMethods
{
    public static string TryToGetTheString<T>(this T value, Func<T, string> method)
    {
        try
        {
            return method(value);
        }
        catch (Exception)
        {
            return "banana";
        }
    }

    public static string TryToGetTheStringTwo<T>(this T value, Func<string> method)
    {
        try
        {
            return method();
        }
        catch (Exception)
        {
            return "banana";
        }
    }
 }

И следующий самоссылающийся класс.

 public class testClass5000
 {
     private int? _id;
     public int? ID { get { return _id; } set { _id = value; } }

     private string _urgh;
     public string Urgh { get; set; }

     public testClass5000 tc5k { get; set; }
 }

Затем, используя чрезвычайно ленивый процесс, чтобы избежать проверки на нулевые значения, пытаясь получить строку (Urgh) из testClass5000, вымог бы реализовать методы расширения и класс, подобный этому,

    private void main()
    {
        var tc = new testClass5000();

        textBox1.text = tc.TryToGetTheString(x => x.tc5k.tc5k.tc5k.Urgh);

    }

Однако, поскольку tc объявлен локально, также работает следующее.

    private void main()
    {
        var tc = new testClass5000();

        textBox1.text = tc.TryToGetTheStringTwo(() => tc.tc5k.tc5k.tc5k.Urgh);

    }

Мне любопытно, когда необходим (x => x.tc5k.tc5k.tc5k.Urgh) икогда (() => tc.tc5k.tc5k.tc5k.Urgh) предпочтительнее.

////////////////////////////////////////////

Я придумал следующий сценарий, в котором передача параметра представляется предпочтительной.

С помощью следующих методов расширения.

public static class ExtensionMethods
{
    public static T TestOne<T>(this T value, Func<T, T> method)
    {
        try
        {
            return method(value);
        }
        catch (Exception)
        {
            return default(T);
        }
    }

    public static T TestTwo<T>(this T value, Func<T> method)
    {
        try
        {
            return method();
        }
        catch (Exception)
        {
            return default(T);
        }
    }
}

И используяследующий код.

    private void Form1_Load(object sender, EventArgs e)
    {
        var firstValue = 5;
        var secondValue = 10;

        var resultOne = firstValue.TestOne(x => x + 1).TestOne(x => x * 2);
        //returns 12
        var resultTwo = secondValue.TestTwo(() => secondValue + 1).TestTwo(() => secondValue * 2);
        //returns 20
        var resultThree = secondValue.TestTwo(() => secondValue.TestTwo(() => secondValue + 1) * 2);
        //returns 22
    }

В этом примере .TestOne (x => x + 1) .TestOne (x => x * 2) является предпочтительной нотацией, потому что для достижения того же результата без передачи нужного вам пареметраначать вложенные выражения.

Ответы [ 2 ]

4 голосов
/ 02 декабря 2011

Внедрение значений параметров непосредственно в лямбду более затратно, потому что компилятор должен создать специальный класс именно для этой цели.

Если мы исключим соображения производительности, то я бы сказал, что введение параметра легче написать (здесь это личное предпочтение), а сохранение параметров в прототипе ((x, y) => // делать что-то) полезно, когда вы на самом деле не тот, кто предоставляет значение параметров. Например, при использовании запроса Select Linq. Или я часто использую это для сценариев балансировки нагрузки (лямбда "service => service.SomeFunction ()", затем специальная фабрика получает сервис и выполняет лямбда).

3 голосов
/ 02 декабря 2011

В тех случаях, когда параметры просто не совпадают с предоставленным вами исходным значением.

Грубый пример

public static class Extensions
{
    public static void DoSomething(this string s,Action<string> action)
    {
        var something = Enumerable.Range(1,100).Select(i=> String.Format("{0}_{1}",s,i));
        foreach (var ss in something)
        {
            action(ss);
        }
    }
}

Тогда

var something = "ABC123";

something.DoSomething(x=>Console.WriteLine(x));
//Ignoring that we could do something.DoSomething(Console.WriteLine);

Очевидно, что безпараметр, к которому вы не можете получить доступ к фактическому значению, в котором вы заинтересованы, и исходное значение в этой концепции бесполезно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...