Функціональний делегат без повернення


561

Усі делегати Func повертають значення. Які є .NET-делегати, які можна використовувати з методами, які повертають недійсність?

Відповіді:


759

Усі делегати Func щось повертають; всі делегати Дії повертаються недійсними.

Func<TResult> не бере аргументів і повертає TResult:

public delegate TResult Func<TResult>()

Action<T> бере один аргумент і не повертає значення:

public delegate void Action<T>(T obj)

Action є найпростішим, «голим» делегатом:

public delegate void Action()

Є також Func<TArg1, TResult>і Action<TArg1, TArg2>(та інші до 16 аргументів). Усі вони (крім Action<T>) є новими в .NET 3.5 (визначені в System.Core).


11
FYI, наступна версія бібліотеки базового класу буде включати типи функцій та дій, які підтримують більше чотирьох формальних параметрів. Я не пригадую, як саме вони отримують великі.
Ерік Ліпперт

88
У .NET 4.0 вони тепер переходять до 8 параметрів. Якщо вони продовжуватимуть це, то в наступній версії він підніметься до одинадцяти !! 11 !!!
Міхель ван Остерхаут

9
Насправді, схоже, вони піднімаються до 16 в 4.0.
Tustin2121

7
1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, ... це чітко вказує на те, що компілятору потрібно мати можливість справлятися з більшою кількістю аргументів функції, ніж це в даний момент в майбутньому !
Кріс Морган

6
Власне, Tustin2121 має рацію, вони підняли до 16 параметрів (плюс тип повернення у випадку Func<,,, ... ,>) у .NET 4.0, але останні вісім типів кожної "серії" визначені в System.Core.dll, а не в mscorlib.dll, тому це буде причиною чому michielvoo їх не бачив. Однак більше. Функцій чи дій не додано у .NET версії 4.5 та 4.5.1. Чи стане ця послідовність A170836 або A170875 ? Слідкуйте за налаштуваннями.
Джеппе Стіг Нільсен

83

... не бере аргументів і має тип недійсного повернення?

Я вважаю Action, що це рішення для цього.


47

Усі делегати Func приймають принаймні один параметр

Це не правда. Усі вони приймають принаймні один тип аргументу, але цей аргумент визначає тип повернення.

Таким чином, Func<T>не приймає жодних параметрів і повертає значення. Використовуйте Actionабо Action<T>коли ви не хочете повертати значення.


27

Спробуйте System.Func<T>іSystem.Action


1
Я не думаю, що 0 arg і те, що не існує в. Net 2.0, хоча.
Брайан

1
Це дивно: Func взагалі не існує в .Net 2.0, хоча це і предикати, і дії.
Joel Coehoorn,

2
Для .NET 2.0 використовуйте делегат MethodInvoker.
Тревор Елліотт

.NET 2 також мав (або має) тип делегата, Converter<TInput, TOutput>який був подібний до більш пізнього Func<T, TResult>. Він був використаний у List<>.ConvertAllметоді, який проектував кожен елемент List<>на інший об'єкт і розміщував усі "значення функції" в новому List<>. (Пізніше часто Selectдля цього можна використовувати Linq .)
Джеппе Стіг Нільсен

0

Іноді ви хочете написати делегата для обробки подій, і в цьому випадку ви можете скористатися тим, System.EvenHandler<T>що неявно приймає аргумент типу objectна додаток до другого параметра, з якого слід виходити EventArgs. EventHandlers повернетьсяvoid

Я особисто вважав це корисним під час тестування для створення одноразового зворотного дзвінка у функціональному тілі.


0

... не бере аргументів і має тип недійсного повернення?

Якщо ви пишете для System.Windows.Forms, ви також можете використовувати:

public delegate void MethodInvoker()

0

Дуже простий спосіб викликати підпрограми повернення та неповернення. використовує Func та Action відповідно. (див. також https://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx )

Спробуйте цей приклад

using System;

public class Program
{
    private Func<string,string> FunctionPTR = null;  
    private Func<string,string, string> FunctionPTR1 = null;  
    private Action<object> ProcedurePTR = null; 



    private string Display(string message)  
    {  
        Console.WriteLine(message);  
        return null;  
    }  

    private string Display(string message1,string message2)  
    {  
        Console.WriteLine(message1);  
        Console.WriteLine(message2);  
        return null;  
    }  

    public void ObjectProcess(object param)
    {
        if (param == null)
        {
            throw new ArgumentNullException("Parameter is null or missing");
        }
        else 
        {
            Console.WriteLine("Object is valid");
        }
    }


    public void Main(string[] args)  
    {  
        FunctionPTR = Display;  
        FunctionPTR1= Display;  
        ProcedurePTR = ObjectProcess;
        FunctionPTR("Welcome to function pointer sample.");  
        FunctionPTR1("Welcome","This is function pointer sample");   
        ProcedurePTR(new object());
    }  
}

1
Дякуємо за цей фрагмент коду, який може надати деяку обмежену, негайну допомогу. Належне пояснення було б значно поліпшити свою довгострокову цінність , показуючи , чому це хороше рішення проблеми, і зробить його більш корисним для читачів майбутніх з іншими подібними питаннями. Будь ласка , змініть свій відповідь , щоб додати деякі пояснення, в тому числі припущень , які ви зробили.
iBug
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.